 Hi there, my friend and friends. What if you had a layout like this one where we want to change it was the viewport gets smaller, right? And then everything is just going to stack. But then maybe that's not what we want because I'm actually using this with sidebar in a couple of different places. I have it in here and I have it in the bigger layout. And I sort of want this one to collapse earlier. I don't want to have to make a new class because it's the same behavior. Well, we have container queries now. That's great. So I can update that to a container query to make sure that they're well set up so this can actually work. But now you can see that here I have the two columns that want to get the wider, that third columns coming in because now this area has that 750 width and that's going to work. That's great, except it's still kind of magic memory. Like where do I want that break point to be? I just have to sort of figure out, like, okay, it's around 750 when things are starting to get a little bit too narrow here and that's when I want it to switch and I look here and yeah, I guess that works. Maybe even I need to update that and that number is not perfect can be kind of hard to pick the right value to put here. Well, what if I told you there's a way of doing that where we can say what the size of the main area we want is? I'm defining this area. And when this area passes a certain threshold, we're going to have our break point instead. Then because I had that same thing nested inside of here as this is getting bigger, that one, once this can fit down to that 45 CH, then that next column is going to come in and everything just works that way instead. No media queries involved, no container queries and it's all based just on the size of this element. And we can do this with grid too, where we can say we want a minimum column size, how many columns we want and we can just have it go from stacked to having those columns and that's just the break point will happen, not based on the viewport size, not based on the container size, but based on when these have 200 pixels to live, they can all fit next to each other, then it's just going to happen. If I need to change how many columns I have, I can change how many columns I have and then it's just going to work and I can change the size and everything else to go along with it. Well, if this seems like something that might be useful to you, then you're in the right place because we're going to be diving into this. Now, just before we dive into the actual content, I just want to let you know I do have some new merch. Here's my new color space T-shirt. I have a grid T-shirt, I have a cascading style sheet one. You'll be able to see them just down below this video if you're interested in some. I really like them. I think they look really nice and good and you can also tell everyone that you're now a front end friend as well, you can advertise that fact. So if you'd like one, link down below. But with that out of the way, let's dive in and jump into the code and see how we can do all of this. And what we're going to be actually starting with here, you can see I've set up the markup we need in place and I just have some basic styling here. Just really fast, all I'm doing is I have this with sidebar in my HTML and then in the with sidebar, I just have to have two elements and then it's going to be an element with a sidebar. And then if I look inside my main, I've done the same thing. I have another section here using the same with sidebars. This is just to nest it down below. In this case, it's a section and it's just two divs right there and there and it's going to work. If you want a different naming convention or whatever it is by all means, go with whatever you want to call it. But yeah, that's what we're going to be starting with there. And you can see here in my CSS, all we're starting with is I've given some styles to my with sidebar. These aren't being used anywhere yet other than the gap, which is coming right here. But the important thing is we do want to be using display flex for this. If you want the grid solution and gonna get to it after and if you'd rather just skip to that, there is the timestamps down below, though the grid one sort of builds on what we're doing here. I think this one's a bit easier to understand to see how the grid one works, but it's up to you in what order you'd want to go in or if you do want to skip ahead. But we're going to have our gap that's on there and we do want to have this flex wrap on there. This is part of what makes everything possible. Now there are some other styles being applied here. As you can tell, they're just all much further down and they're not related at all to how this layer would work. So we're going to isolate the parts that are important for what we're building out in this example right here. So the first thing I need to make this work is I want to choose the first child that's in there because the way I'm setting this up is the first one would always be the larger one. If you'd want to have to like assign classes to those you can, but in my case, I'm just saying the first thing is my main area that then has a sidebar or whatever. So the first child is going to get a flex grow of 9999 on it, which just means it's going to try and be as large as possible. This is going to be important in just how this behavior is working. It is a little bit of a flex box hack, but it is definitely what enables this to actually be a thing that works. It doesn't have to be 9999, but it does have to be something fairly substantial because then we're going to do our last child here. And this one's going to have the flex grow of one on it. Meaning we need it to grow. So when they're wrapping down like this is doing right now we want it to be able to take up all the space. The thing is when they go next to each other, if they both have an equal flex grow, they're going to try and take up an equal amount of space. And maybe we'll check that out in a second, but by putting this as a flex grow 9999, it means the growth factor is so much bigger here than it is here that this one is going to just try and take up all of the room. And it basically prevents this one from actually growing. Now, where things get weird is this line of code. And I'm going to just paste it in and we're going to sort of explore what it's doing a little bit. And granted, this looks very strange. And someone might go, Kevin, you shouldn't be doing this. This is unreadable. It's a mess. No, it isn't a mess. It's complicated. It makes sense once you understand what it's doing. And it's one of those things that you don't have to come here and ever touch this. This is how you maintain this. If you need a third column or something, you're making a new component. Anyway, I've talked about this in depth in another video where I sort of actually talked about this but I went really fast over it. But I would, if you think this is too complicated in terms of maintenance and readability, I 100% disagree with you but I'll link to my other video where you can yell at me why I'm wrong in the comments over there instead of over here. This one, we're going to stick with the positivity and just look at how this is working and how we can get it to work properly. Where you can see, look at that. We actually have something going on now. So basically what's happening is we're saying we're going to take this min width. So let's just, we'll come down here and we'll put a comment. We're going to say 750 pixels because that's the number we've put, minus. And then here we're doing 100% minus 250 pixels minus two RAM, so I'll just write 32 pixels. Yeah, 32 pixels. And let's ignore that 9999 at the end for now. So we're saying 750 and let's just say we said minus 100%. So if we're only doing minus 100%, what that would mean is when the parent's size, because the 100% is always looking at the width of the parent of the element. So when the parent's size gets past 750 pixels in width, we'd have 750 minus a larger number than 750. So if this number is larger than 750, and actually, let's just, again, we'll come back to this for a second. If this, the parent's size is larger than 750 pixels, this is going to turn into a negative number. And flex basis can't be a negative number, so it basically calculates it as zero. So if it calculates it at zero, but then we have a flex grow on it, it's saying we're zero pixels, we have room to go next to each other, but I have a flex grow, so I'm gonna grow to fill up the available space. And because the flex grow is at 9999, it's going, I'm going to be super big. And so it just grows and it fills up as much space as possible. That's it. We're becoming the negative value, and then it's trying to grow to fit that space. And then the reason I'm also incorporating these two numbers in it is because I don't want this to only act when the viewport or the parent container, I should say, when the parent gets to 750 pixels, I want to subtract 250 pixels from that and subtract my gap from that as well. So because we're looking generally, we're trying to subtract the parent size. We have 100% is the entire thing, but from that 100%, I want to subtract this sidebar, and I want to subtract this element that's right here. So by saying the entire thing minus the size that this stuff on the side is taking up, then that's actually gonna click in when this is it exactly or very close to, it might not be exactly, but it's gonna be very close to 750 pixels. So this is where, and you'd probably lean into a more intrinsic way of doing it. I've say 45 CH. So then it's working great with that 45 CH, and it's a very common way to work with typography, and then eventually this will kick in too. Now one thing I haven't done, you can see this is taking up too much room right now, is because my last child, we'd said we wanted that 250 on there. So here what we're gonna do is to fix that is a flex basis of the var sidebar size, and that sort of gives it, like this is the size it wants to be, like the ideal size when you're dealing with flex basis, and we have a flex grow and a flex shrink on there, but it won't grow bigger than that just because of our gigantic flex grow over here. But that gigantic flex grow over here won't cause this to shrink smaller than we want it to be. So the sidebar will still be hovering around that 250 size. If we come and take a look at the computed styles for the sidebar, 218 plus 16 plus 16 gives you 250, so there's a little decimal place in there too, but it'll be pretty close to what you want, but because we have a flex grow, once it wraps down, it will wrap, it works there, and it works a lot like a container query as well because you can see it's working, the same pattern is working within this element as well, but only once this one has enough room. So it works really well. I think it's a really cool pattern and I like it a lot, and as I said, we can take that and make it work with grid as well. And a little bit of a different way. And what I like about what we're gonna do here with the grid is if you did this with, and actually we're gonna start with this, so we'll see it as an example. I'm gonna say grid template columns, and then usually what we have is a repeat, and then you do an auto fit, and in the auto fit, you might say a min max of 320 pixels, one FR or something like that, right? So then we're gonna get columns, but the browser's figuring out how many columns there should be, and I love this. I think this is a fantastic way to work. I use this all the time. It's really, really handy. But sometimes you don't wanna go from one to two to three to four. You want one, and then it goes to three, and it just stays there. But you don't wanna necessarily do that with media queries, because again, then you're basically just magic numbering and figuring out where that's gonna happen. So for me, what I like is we can set that up using a similar idea to what we just looked at, but we're saying once my columns can be 200 pixels, I want two of them. Or once my minimum size is 400, and I want three of them, or whatever you need. So we'll look at how to do that. In terms of the HTML itself, it's super simple. I have my columns set up. I guess that should be more grid, but whatever. Then I just have my divs in there. There's nothing else. There's no fancy things. You just place whatever content you want to be on there, and it will live in the grid that we're creating. Now, for this one, I find an easier way to work. This is sort of like the user settings. Let's do that. We're gonna see user settings are gonna be here. And then to make things a bit more readable, we're gonna have like calculations. And I'm gonna do this just because it's gonna make it a bit easier when we update this to make it work, just to understand exactly what's going on. So the calculations we're gonna want is to figure out what our break point is, and we're gonna do a column size calc right here or something just so it's not like, I don't want it to get confused between the two of them. So for my break point, we're gonna do a calc. And we need to figure out like, when is this going to be breaking? What's gonna cause it to happen? Well, I wanna take my minimum column count. So we can do our var minimum column size. I said count before, but we need both of them. So we have our minimum column size. And then we're going to multiply that by our column count. Because what we need is we only want this to get activated once we have enough room for these to be 200 pixels each. And depending on how many columns I need, we need that total amount of space available. So we're gonna multiply those together. So by doing that, then that gives us that number. The only problem is we have to account for gaps as well because when we're dealing with like set numbers like this, the gap does play into it. And if you don't set it up properly, then you'll be missing a column and it's kind of awkward. So we need to account for the gap, but the problem is the gap doesn't exist on every element. It exists in between all of the elements, right? So still inside of my calc here, we're gonna do plus my gap, but the gap itself, we're gonna have to multiply by var column count because we need it for every one of the columns except for one of them. Because as I said, it's in between every column. So if you have two columns, you only have one gap. If you have three columns, you only have two gaps. If you have 10 columns, you only have nine gaps. So we wanna do times our column count minus one. So it is a fair amount of math here that has to go into it. The logic of it, I think is very straightforward, but yeah, not the first thing you'd probably think of along the way. And then also I'm just gonna take all of this and wrap it together just cause I wanna make sure like order of operations will make sure this is happening first, but I wanna make sure that like this entire thing is getting handled on its own as one calculation that gets brought into the rest of it. So I'm just adding an extra parentheses around this section right here to make sure that's, you know, that gets done. Then we can multiply these and then add those two numbers together. And it gives us exactly what we want. The other thing is the column size calc. And this is because we're saying we want our columns to be 200 pixels. That's great for us. But if we said 200 pixels, then they're just gonna get locked into 200 pixels. We don't want them to be 200. We want that to be the minimum size. So because we want it to be the minimum size, but that minimum size still needs to be like a flexible number. We do have to do a nice little bit of math here as well. So once again, it's our calculations. So we're gonna use a calc. I do wonder, and actually if anybody has a suggestion on if we can eliminate this, I tried doing a few different things because we're still gonna use them in max down here. So if you have a way of doing it, please leave a comment down below. But everything I tried, I had to do a calc here. And so what we're gonna do is we're gonna say it's 100% and then we're gonna divide it by my var column count. Now it's not everything we need, but that's the first step we wanna do just because every one of our column sizes now, if we take 100% and we divide it by two, it's 50%. So we have our two columns divided by three. We have our three columns divided by four. We have four columns. That makes sense. But once again, gap sort of ruins our fun on this one. So we're gonna do that. Now the problem with 100% is once again, it doesn't take into account the gaps. So if we just left it like this, we'd have a sort of the gap left over and our column count wouldn't work properly. Actually I said that for the gap here. The gap here was just to make sure that it's happening at the right spot. Here we need to do it to ensure that we have the right number of columns. So we need to bring that back in. So I wanna make sure this is happening first. So we're gonna wrap that in its own set of parentheses and then we're going to come over here and we're gonna subtract our gap value. So minus var gap from that, which should now allow this number to be what we need it to be. I tried setting this as an FR and the whole thing fell apart. So I couldn't do it with the FR unit here, which ideally we, if we could do it with FRs then I could get rid of this right here, but for whatever reason I couldn't. So a slightly more complicated calculation, but it's not that bad. Now where things get funky is where we bring it in here. So we're gonna have our repeat and then we're gonna have our auto fit, right? Then down here on this min max, I'm gonna put things on their own lines just so it makes it a little bit easier to read just cause this min max is a little bit weird. So even in this min max, let's come and put these each on their own line just to make things a little bit more readable. We'll go like that. So this is technically my minimum and then my maximum is one FR. The one FR is what allows it just to stretch the full size. So if we can't go, then here we'll get to here. If it doesn't work, then just keeps growing. So the minimum size is this one, the maximum size is that one. In this minimum though, what we're going to do now is we're gonna put a min function. And this is important because if your column size here is something big, let's say it's something like 600, we don't want it when we get to these smaller sizes. Let's just, here, I'll just do this, 600 pixels. You're gonna see that it causes overflow, right? Because the smallest it can get to is that, which we don't wanna happen. So we want that column size here and then here I'm gonna come after and I'm gonna say 100%. This is a very common pattern to use within the auto fit which just means that when you get smaller, choose the smaller of these two values. So it's gonna try and be the 600 and when it can, it's still going to work. But when we get smaller than 600, it's going, the 100% is smaller than this, so they'll continue shrinking and you won't get any horizontal overflowing. Cool. Now, instead of 600 pixels here, we want something else. What do we wanna use? Well, we have two different things. One of them is we have our column size calculation that we used here. Maybe I'm just gonna call this column size, whatever. This is my min column size. This is the actual calculated column size. I think it just makes more sense calling it that down here. So in this min, we can start off by just putting that in var and then we can say that it's our column, column size, right? And that's exactly what we just have now. Now, the problem that we have is this is always smaller than 100% because the calculation here is literally 100% divided by, right? So we basically just said it's always gonna be two columns now. So you might be saying, well, we don't need the min function here. We are going to need the min function here, don't worry. Because what I actually wanna do now is inside this min function, I'm gonna put a max function. And so we're gonna wrap this. And again, if you're going, Kevin, the maintainability or the readability of this is garbage, go watch my other video because I disagree with you and you'll have to see that one to know why. So this is the first value in our max function and then we're gonna put a comma and after the comma, we're gonna say 100% minus var breakpoint. And then so that right now, I think that's not actually gonna do anything just yet just because of where this is happening, but we're gonna do that thing we did last time where we're gonna say times. And in this case, instead of 9999, I wanna do a negative 9999 to make it a really big negative value. And it's sort of to flip on its head what we were doing last time. And the last thing here is I just do wanna make sure that this is calculations getting done before the multiplication. So we're just gonna wrap that because order of operations will kick in, if not, and the multiplication will happen at the wrong size. And with that, it should work and it's not working. And I realized why is because over here, again, order of operations, I wanna make sure that this minus one is happening before this multiplication because if not, that's mucking it up. We wanna do the column count minus one times our gap so we can add an extra set of parentheses there just to make sure that's happening. And look at that, now it's working. We have two columns kicking in when each one can be 600. I want it to be 400, they become at 400. I want it to happen, have three columns when there's room for all of them to be there. So you can see it's much wider because again, we're basing it not based on the container size, but based on the content size. When the columns are smaller than 400 pixels, it's going to switch on over. And then in this case, maybe whatever, you can come up with different numbers, whatever you need to fit. And actually we can't get to that size. But you get the idea of how it can work. And the nice thing with this is, this is all based on where this is being used. So I'm just using my wrapper now to hold everything but just, if I say that's 10, it's not based on the viewport size, it's based on the size these elements have available to themselves. It looks really weird, it's definitely really strange, but once you have this set up, you have these things set up. And if you're like, Kevin, I can't get it to work because I'm missing parentheses or whatever along the way. The finished code is linked down below. So you can get it there and just copy paste this. And then all you're ever doing is updating this. And you should never have to worry about anything. This should control everything, it should work in basically any situation you throw at it. The only time sometimes these types of things fall apart a little bit is if you try and push the limits too small every now and then I see them not working. And just really fast, if you're wondering why we need this min 100% is if I take off this 100% here and I take off the min function we have right there, so we're only using the max, when this clicks in, these are becoming gigantic. Like this is scrolling on forever because the number has become so big. So here it's working, here it's working, but as soon as we hit that threshold, because we're choosing which one's bigger, this one or this one. So when this is a negative number, it's really small. So, and that's basically once we've, you know, passed our break point, we're getting a really small number and in those cases everything is fine, the bigger of the two of them is going to be my column size. But once we go to there, this becomes my size and it just makes them gigantic. And so that's why if we then come in with our min and the min with the 100% here means when they become gigantic, we're actually gonna choose the smaller of those two potential values and it's going to just fit. So it's kind of weird, we have a min with a max, inside of min max, but it is what it is, it works really well. And I'm curious, do you like this idea or do you not? Do you think there's other ways, simpler ways of doing it? You're fine with container queries, you're fine with media queries when you need them or you're like, Kevin, this makes a lot of sense and I could use this type of thing in my project. And I'd like to know more stuff we can do like this. Whatever the case is, let me know down in the comments what you think, just so I know what type of content to continue bringing you in the future. And with that, don't forget, if you are interested in any of the new merch, the links are down below for that. And a huge thank you to my enablers of awesome Andrew, Simon, Tim and Johnny, as well as all my other patrons for their monthly support. And of course, until next time, don't forget to make your corner of the internet just a little bit more awesome.