• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

(Flexbox) Newbie question re: items-per-row

Engaged ,
Oct 28, 2024 Oct 28, 2024

Copy link to clipboard

Copied

I'm currently teaching myself Flexbox (via css-tricks) and although everything seems straightforward enough at first glance, I find myself struggling to get the following simple behavior working correctly.

 

Basically, I'm going for something like this...
<div class="container">
     <a href="#">Stuff</a>
     <a href="#">Stuff</a>
     <a href="#">Stuff</a>
     <a href="#">Stuff</a>
</div>

...where a row of 4 anchor tags (or possibly span tags) becomes two rows of 2 tags when the width of the container becomes too narrow for 4. So I want it to skip the 3 & 1 scenario and go right from a row of 4 to two rows of 2. (Even numbers, never an orphaned option alone on a row.) These content "boxes" (a or span) should be of equal width to one another, and top-justified (so if one has more content than the others, it will be vertically longer, but equal-width and top-justified).

With Grid, they were columns so I'd just tell the grid to go from 4 colums to 2 via a @ Media screen declaration, when the viewport got narrower than X pixels. So I'm kind of looking for the Flex equivalent of that behavior (or the closest thing to it).

 

What would that css look like? I sometimes find it easier to reverse-engineer from the solution.
Thanks!

TOPICS
Code , How to

Views

461

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Community Expert , Oct 28, 2024 Oct 28, 2024
.container {
    display: flex;               /* Use Flexbox layout */
    flex-wrap: wrap;            /* Allow items to wrap onto multiple lines */
}

.container a {
    flex: 1 0 25%;              /* Basis of 25% for four items in a row */
    border: 1px dotted red;    /* Thick border for visibility */
    box-sizing: border-box;      /* Include padding and border in width */
}

/* Media query for widths below 600px */
@media (max-width: 600px) {
    .container a {
        flex: 1 0 50%;     
...

Votes

Translate

Translate
Community Expert ,
Oct 28, 2024 Oct 28, 2024

Copy link to clipboard

Copied

.container {
    display: flex;               /* Use Flexbox layout */
    flex-wrap: wrap;            /* Allow items to wrap onto multiple lines */
}

.container a {
    flex: 1 0 25%;              /* Basis of 25% for four items in a row */
    border: 1px dotted red;    /* Thick border for visibility */
    box-sizing: border-box;      /* Include padding and border in width */
}

/* Media query for widths below 600px */
@media (max-width: 600px) {
    .container a {
        flex: 1 0 50%;          /* Basis of 50% for two items in a row */
    }
}

By setting the flex property of the anchor tags to 25%, the layout accommodates four tags in a row. Upon reaching a specified breakpoint of 600 pixels, the flex property adjusts to 50%, allowing for only two tags per row.

This strategy guarantees that the layout maintains even distribution and avoids orphaned tags, aligning perfectly with the specified design requirements.

 

You can watch the result https://demo.puce-et-media.com/UnderS/flexbox-1.html

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Oct 29, 2024 Oct 29, 2024

Copy link to clipboard

Copied

Thank you, that is beautiful and exactly the behavior I'm going for. Can't wait to try this later.

 

About 'box-sizing: border-box' -- I have it applied to my html & body tags (so regardless how many different boxes there are on the page, the padding is always factored into the dimensions. Frankly, I think it's weird that border-box *isn't* the default behavior. Never had a problem so far, do I risk encountering any later? (By making border-box the default box-sizing behavior for the whole site, I mean.)

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Oct 30, 2024 Oct 30, 2024

Copy link to clipboard

Copied

@L e n a  Finally got to try the code! Love the results, with one caveat : "box-sizing: border-box" doesn't appear to be kicking in. As soon as I add a gap space, the container's width becomes 100% + gaps. In fact, the results appear identical with and without the box-sizing line included.

 

I suppose I can work around this with a "calc", but I'd rather not get that convoluted with the code if it can be avoided. Any theories on why this could be happening, or suggestions for solutions that don't involve substracting the manually-specified gap-length from 100% via "calc"?

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Oct 30, 2024 Oct 30, 2024

Copy link to clipboard

Copied

One way, assuming it's a gap between the anchor tags you are requiring - set the css on the anchor tag to less than 25%, say 23%, and apply  align-content: space-between; on the 'container ' css.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Oct 31, 2024 Oct 31, 2024

Copy link to clipboard

Copied

Good thinking. With 4 sub-groups and 3 gaps of 1.25em, I was going to use something like width:calc(100% - 3.75em) on the container. Would your method be a more elegant solution? Or would the two methods work equally well, with neither having much advantage over the other?

 

PS: I'm still a bit annoyed that the box-sizing fix didn't work on gaps like it works on padding. I mean the property is old as heck.. maybe it just doesn't play well with Flex, which is newer? Could Flex have its OWN proprietary equivalent to box-sizing: border-box that would fix this?

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Oct 31, 2024 Oct 31, 2024

Copy link to clipboard

Copied

I don't see anything incorrect in using your solution......in fact you should be able to control the gaps more accurately using calc.

 

My advice would be to use what is familiar to you and that which you feel comfortable deploying..............there's many ways which can be used to arrive at practically the same result.

 

Doesn't grid also suffer the same issue where padding gets added to the width of a container despite using box-sizing: border-box? Somewhere in the back of my mind l seem to recall it does.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Oct 31, 2024 Oct 31, 2024

Copy link to clipboard

Copied

Yes, grid has the same issue. So neither function seems to consider gaps as padding. Wouldn't this suggest that it's the box-sizing property that's at fault, here? If so, the only obvious fix for this would be to update box-sizing at the root level to take these cell gaps into account like they already do with padding. Until then, we'll probably be hacking fixes; like back in the Internet Explorer days.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Oct 29, 2024 Oct 29, 2024

Copy link to clipboard

Copied

Foĺlow Lenas advice or you can wrap the pairs of  "a" tags in divs and apply the  css attribute white-space: nowrap; to the divs, which will force the pairs of "a' tags onto a seperate line at any screen width which won't accommodate them, without using media queries, although on smart phone screens you may possibly want each 'a' tag to be on its own line...............so plenty to think about.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Oct 29, 2024 Oct 29, 2024

Copy link to clipboard

Copied

I considered asking Lena to fix it so the 4 not only become 2 (when the viewports gets under X pixels) but also, as you are suggesting here, the 2 becoming 1 in even narrower spaces like smart phones... but a) I honestly have zero immediate need for that, and b) I figured I might be able to edit the code myself (to do just that) once I really absorb what Lena did, and how. If I was wrong, I'll be back for more pointers. 🙂

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Oct 29, 2024 Oct 29, 2024

Copy link to clipboard

Copied

There are so many viewport variations these days you may need to deploy a lot of media queries to achieve the desired effect across a range of devices. When l deployed a set of icons and didn't want a widow icon on one line the extensive amount of media queries l had to use became an issue so l used 'white-space nowrap' which does the job more automatically and caters for any size viewport rather than media queries which only activate at certain viewport widths.........l was exploring a more robust option to cater to a wider amount of devices automatically.

 

Maybe lm unusual but l frequently widen and narrow my browser viewport on a Mac so if there's no media query to  cater for the varying widths the intended design outcome doesn't always work.

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Oct 31, 2024 Oct 31, 2024

Copy link to clipboard

Copied

Sorry I was in location and just get back now...

In fact it all depnd about your way, and what you want to learn...  @osgood_ propose a nice way to go too...  just explore it...

 

now sticking to tthe previous approach, there are as many solutions for integrating a gap as there are developers on this thread... although sometimes, for this kind of need, grid is more direct and simple... in any case, here are a few ideas for aligning 4 elements in a row, or 2 or 1 alone, depending on the width of the available screen and also now integrating a gap

 

Approach 1: Flexbox with Margin

.flex-container {
    display: flex;              
    flex-wrap: wrap;            
    margin: -5px;               /* Negative margin to offset child margins */
}

.flex-container .box {
    flex: 1 0 calc(25% - 10px); /* Basis of 25% minus margin */
    margin: 5px;                /* Margin for spacing */
}

Each box got, as you was exploring, a property flex: 1 0 calc(25% - 10px). So it means each box will take about 25% of the container width, minus 10 pixels for the margin (5 pixels on each side).

The negative margin on the container is helping to offset the margin applied to each box, so they stay aligned good without overflowing the container.

Then with media queries, when the screen width is less than 900 pixels, just adjusts to 50% for two boxes, and when it’s less than 600 pixels, apply 100% .

@media (max-width: 900px) {
    .flex-container .box {
        flex: 1 0 calc(50% - 10px); /* Basis of 50% for two items in a row */
    }
}

@media (max-width: 600px) {
    .flex-container .box {
        flex: 1 0 100%;          /* Basis of 100% for one item in a row */
    }
}



 

Approach 2: CSS Grid

.grid-container {
    display: grid;              
    grid-template-columns: repeat(4, 1fr); /* Four equal columns */
    gap: 10px;                  /* Gap between items */
}

Use display: grid property for create a grid layout and apply a grid-template-columns: repeat(4, 1fr) to define four columns in the grid.

The 1fr unit means that each column will have each an equivalent width from the available space, so they will adapt when the screen size changes.

Then gap: 10px property define the gap between each items whatever their width is.

Now, when the width is below 900 pixels, switch the grid-template-colums to 2, and below 600 pixels to just 1. 

@media (max-width: 900px) {
    .grid-container {
        grid-template-columns: repeat(2, 1fr); /* Two columns */
    }
}

@media (max-width: 600px) {
    .grid-container {
        grid-template-columns: 1fr; /* One column */
    }
}

 

 

Approach 3: Flexbox with Gap

.flex-gap-container {
    display: flex;              
    flex-wrap: wrap;            
    gap: 10px;                  /* Gap for spacing */
}

.flex-gap-container .box {
    flex: 1 0 calc(25% - 10px); /* Basis of 25% for four items in a row */
}

you can also use Flexbox again, but this time take advantage of the gap property to manage the space between the boxes.

gap: 10px , that will automatically creates a space of 10 pixels between the flex items

no need to play with margin anymore... but... while the gap property works well beside Flexbox in modern browsers, it’s not supported in all versions. 

 

That should do the job for testing purpose  https://demo.puce-et-media.com/UnderS/flexbox-2.html

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Nov 06, 2024 Nov 06, 2024

Copy link to clipboard

Copied

So much to learn from here, thank you!

I have everything working perfect, and have only one last question about what we used to call "colspan" back in the Table days. In a flex container that sets sub-divs at 25% each, how do I make one of them occupy two spaces (ie, 50%) of the row in some situations? (What's the code I can use directly on that sub-div to tell it take up twice the usual width?)

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Nov 07, 2024 Nov 07, 2024

Copy link to clipboard

Copied

I assume you have 3 cols?

 

2 which span 25% each and 1 which spans 50%?

 

Try:

flex: 1; /* for the cols which span 25% */

 

flex: 2; /* for the col that spans 50% */

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Nov 07, 2024 Nov 07, 2024

Copy link to clipboard

Copied

LATEST

I'm glad that it helped you. Concerning your last request, and in order to complete with images, what @osgood_ has told you, I can't recommend enough that you visit the CSS Tricks site - https://css-tricks.com/snippets/css/a-guide-to-flexbox/... #aa-flex-grow is clearly explained.

 

You can also check out MDN's site, where the diagrams are sometimes supplemented by some very instructive technical details https://developer.mozilla.org/fr/docs/Learn/CSS/CSS_layout/Flexbox

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines