can this layout use a flex wrap rather than a media query?

Hey, i made this example for someone with my go to method being that the flex container's flex-direction changes to row in a media query. However i feel like that can be simplified using a flex wrap which i'm trying to learn the in depths of. How would i go about doing this? My first thought was to limit how small the cards can get with width or flex-basis but i'm not entirely sure of the most efficient way to go about it. I'd prefer that the cards don't individually wrap but rather all wrap at once so they can all either be all in a row or all in a column. Or is a media query the most efficient way? Thanks in advance. https://codepen.io/deerCabin/pen/qBzEWKe
7 Replies
Alex
Alex3mo ago
I think a media query is best for what you're trying to achieve. By default, a flex container crams all the elements it can into a single row, and when it can't do that because the elements can't shrink any further, it'll overflow. If you set it to wrap, then once it can't fit all the elements, it pushes the last element in the row onto a new line. Once that happens, the other elements have room to grow again and will fill the line. It sounds like what you want is for the content to switch to a single column that fills the screen when the contents no longer fit on one row, which is not how flex wrapping works. I might be wrong, but I think to achieve this, you'd either need to change the flex-basis/width/inline-size of the children, or the flex-direction of the container, based on whether the container was wrapping/the last element had wrapped, which is not something you can select for in CSS.
Kevin Powell
Kevin Powell3mo ago
If you really want to go with an intrinsic layout for this, you've got to push the limits of flexbox a little 😄 This will work:
.card-group > * {
flex-grow: 1;
flex-basis: calc((600px - 100%) * 999);
}
.card-group > * {
flex-grow: 1;
flex-basis: calc((600px - 100%) * 999);
}
If the parent is > 600px, this returns a negative value, which the browser basically makes 0. Because it's 0, and there is a flex-grow: 1, it makes 3 columns, and they all grow to fill in the available space. When the parent approaches 600px in width, this flips to a very large positive value (because the 100% is now smaller than 600px). And with the flex-wrap on there, they'll stack. There is one issue with your set up though, which means your columns will never be equal in size. The .card has padding on it, while the .double doesn't. Flexbox doesn't take padding into account for how big every element should be, it only looks at the content size (the content box, no padding/border/margin) for all it's calculations, so the middle column will always be smaller... the content size will be made the same for all three columns, but then the left and right one have padding added on, and they get wider. The simple solution is to do something like this:
<div class="card-group">
<div>
<div class="card">...</div>
</div>
<div class="double">
<div class="card">...</div>
<div class="card">...</div>
</div>
<div>
<div class="card">...</div>
</div>
</div>
<div class="card-group">
<div>
<div class="card">...</div>
</div>
<div class="double">
<div class="card">...</div>
<div class="card">...</div>
</div>
<div>
<div class="card">...</div>
</div>
</div>
Also, because you are using flex-grow: 1, for your flex-basis you don't need the 33%, and you really don't need to worry about the gap. They are growing/shrinking anyway, just make sure they all have the same width and you're good, whether that's a flex-basis: 100% or width: 100% or whatever. The advantage then is, it works with 2, 3, 4, or even 20 columns. edit: this is often why you will just see flex: 1, it sets a flex-grow of 1 and a flex-basis: 0, so all the items are the same size.
snxxwyy
snxxwyy3mo ago
thank you both, lots of valuable information there! i appreciate the explanations.
snxxwyy
snxxwyy2mo ago
After some experimenting i have a question: regarding flex-basis: 0; when you say it makes all the items the same size, how come it works like that? Is it because flex-basis by default is auto so if you have a div, since by default the width is 100%, having flex-wrap: wrap; applied would cause them to stack rather than appear in a row unless you apply flex-basis: 0; as it overwrites the default with something else? I'm not quite sure what that something else would be? Like this example for instance. https://codepen.io/deerCabin/pen/OJePNXM
Kevin Powell
Kevin Powell2mo ago
If you don't define a width or a flex-basis, they will try to be their intrinsic content size. Basically, the same as setting width: max-content, but they have a flex-shrink, so they'll shrink down so as to not overflow. If you make it 0, it's basically saying width: 0px, so they all want to be 0px wide, but then with a flex-grow: 1, they all grow by the same amount. You could also get basically the same result with flex-basis: 100% if there is no flex-wrap. They all want to be 100% wide, but they shrink to be the same size I went into detail on all this in this video
Kevin Powell
Kevin Powell2mo ago
Kevin Powell
YouTube
Flexbox is more complicated than you thought
Article on CSS-Tricks: https://css-tricks.com/equal-columns-with-flexbox-its-more-complicated-than-you-might-think/ Flex is a little strange in how it works, and I only recently dove deep enough into it to really understand what was going on, so I figured I'd share my discoveries with you! 🎓 - I have a 4+ hour course that focuses only on und...
snxxwyy
snxxwyy2mo ago
Ah okay I see now, I’ll go check that out, thank you for helping 🙏
Want results from more Discord servers?
Add your server