Flexbox is more complicated than you thought

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
so i did a video a while ago where i looked at one solution to getting even columns and my example was really really similar to this one and in the comments to that a lot of people said well couldn't you have used you know this is i had this selector here and i used a width of 100 on it and it worked and we're going to see that in a second a lot a lot a lot of comments said well couldn't you just use flex one there and i was like yeah you probably could i just didn't want to get into the flex shorthand and then i tried it because i was setting up a new demo and look at the sizes we have a 189 a 221 and a 189 wait they're not the same size no this should be making them all the same and what i'd originally done in mine is i used a width but you could definitely use a flex basis i just didn't feel like deep diving flex basis i was trying to keep it as simple as possible you'll notice here when it's a flex basis of 100 if they're still not equal they're actually closer now than when we used the shorthand of flex one but it's still not all the same and this was like wait th this this really was like oh i don't understand something here that i thought i understood really well and so i had to start figuring out what it was and that's what we're here to explore hello my friend and friends and welcome back to the channel if you're new here my name is kevin and here at my channel we learn about how to embrace the cascade and just fall madly deeply in love with css and if i can't get you to fall in love with it i'm hoping i can at least help you become less frustrated when you are writing it and one of the ways you can be less frustrated by css is to really understand how it works most of the time we get frustrated with it because it does things that we think are counterintuitive but really there's a good reason why that's happening and this video is all about that it's really to understand how flex is calculating everything to get things to be the sizes that they end up being why it does all of that so we're really going to be deep diving it looking at different problems that come up and as i said we'll be exploring a solution as well let's dive into the code and see what's going on all right so here we are in codepen and just so you notice there's a whole bunch of tabs open at the top i will be looking at different examples so we can really understand what's going on the links to all of those are down below and if you go and jump down there and take a look you'll also notice a link to a css tricks article that article is a deep dive of exactly what we're talking about here that i wrote over on css tricks so after you watch this video if you want to recap parts or go over certain things or all of the code pens are embedded plus some extra ones so if you want to check it out the link to that is down below the first thing we're going to do is just we need to understand how flexbox is calculating the sizes of everything and what happens is a lot of the time you see examples like this right we have a flex parent it has a few little things in it and we do a display flex and we show that it makes columns and they shrink down to be a really small size and what a lot of people think at this point is once they understand a bit more about flexbox they're assuming it's the flex shrink that's causing it to shrink but that's not actually the case if we go and look in the devtools and i am in firefox here because firefox has the best visualizations in the world when it comes to flexbox you can actually see the content size here is 70 pixels and there's no shrink going on and just to show you let's just go on the flex item and give these a width of 1000 pixels to make them really big for a second if it is shrinking it tells you here that it is using the shrink so in this case what's happening is there is no shrinking that's going on even though people assume there is that's kind of interesting right and what i'll do is i'll actually come into this guy here and let's just say flex item and add a bit more content to it and he's going to get a little bit bigger because he's fitting the content that's inside of him and that's actually what flex the first step flexbox is doing is it's figuring out the content size it's looking at how much content is in there and how much space it's taking and what that content size is let's turn off display flex here for a second all right so what what's actually happening here is if you know about um it's intrinsically setting and when we see intrinsic i just mean the browser is doing it not me explicitly writing it out and it's pretty much saying width of max content just like that and you'll see the width of max content is going to shrink items down to fit the content that's inside of them and what's really interesting with the width of max content is it won't have any line breaks so here on this middle one here let's just say lorem 100 to add a whole bunch of words and it gets super long there we go and now we actually have horizontal scrolling because the width of that element is set to the content of that element and if you had multiple paragraphs it wouldn't string them all next to each other it would just choose the longest paragraph that would be inside your flex item so it looks at the longest single piece of content and that becomes the width of the element so it's looking at the content to describe to decide it here i'm explicitly setting it but let's just go up here and undo that back to here um so we can see if i do max content it does that and then what the display flex is doing is it's implicitly doing this so it's doing it behind the scenes and then it's using the flex direction of row to actually put them next to one another like we all know and love so there's not actually any shrinking that's happening at this point where the shrinking happens is if we go back and we add in a whole bunch of content now there's a shrink that kicks in and it's going to smush elements down and it sort of tries to figure things out because you can see some of shrunk more than others but it sort of figures things out and smushes everything so how does it do that how does it decide how big things should be so i think what's the first thing that's really important to know is if you don't have a lot of content flex shrink isn't doing anything it's just setting elements to be whatever but flex shrink is extremely important because then if the content is too big we'll see it right here if we if the content is too big and we didn't have flex shrink here i've turned off flex shrink flex shrink zero turns it off we'd get something like that so the first thing it's doing is figuring out the content size once it's figured out the content size it goes does all of this fit inside of my parent so is it overflowing outside of here so let's let's just throw a border on this border two pixels solid red so are these flex items able to fit inside of here and if we look here no they're not if flex shrink was off they're not able to fit inside of there so if flex shrink is on which it's on by default it's going okay we can't fit inside of there so now we need to shrink and we're going to shrink so we're not overflowing the parent how to decide how much to shrink by because sometimes it seems a little bit odd right that first example before i did the flex basis or the flex one on here the sizes were all over the place how does it figure out like the size of each one of these it seems really random when you first look at it and all this is really important to understanding why this doesn't quite work so let's go over to this guy right here to understand how flex shrink is working and you know what i'm going to set on this an outline on the parent outline of 15 pixels solid red just like that um just so we can see it but i'm using an outline so it doesn't have any influence on the sizing of anything because here i've set a width of 600 pixels what we have inside of here is i have my all my flex items we have three flex items once again flex item flex item plex item but the middle one is a flex item quote-unquote big and i set the widths on these so when i explicitly set a width or if you're using flex basis if you use a flex basis it's going to overwrite that max content behavior that we saw so it's no longer looking at the content size we've now we've explicitly declared a width so it's going to use that instead so it's going this one's 300 this one's so we have two that are 300 right here and right here and then this middle guy is 600 but my parent is 600 pixels wide so it doesn't fit hmm that's a bit of a problem so flex shrink comes in and goes well we're going to shrink everything down so it actually does fit and it does this by looking at the total size that everything would be if we didn't have flex shrink and the total size available so 600 plus 300 plus 300 is 1200. 1200 is bigger than 600 so we need to figure out how to squish that down and what's important to know with flex shrink is it's a rate that things shrink by so that's why this middle item is still bigger than these two side items because they're all going to shrink by the same rate and well how do we know what rate it's going to shrink by and usually we don't have round numbers like this and you're not going to be calculating everything but it's really important to understand so what it's doing is it's shrinking each element by here we can see the shrink 1 is minus 150 so it had 300 minus 150. this one was 600 it's now shrunk down by 300 and then this one is also the 300 that shrunk by 150 so the final size there 150 final size 300 and final size 150 so it pretty much took the actual sizes said we have 1200 we need to fit that into 600 if we divide by two it fits so all the sizes just get divided by two and then like magic it fits into the parent as i said it's not always these nice round numbers but it's this concept of how it's figuring out the space that they want to take up figuring out the space available dividing it up and then just making it fit so that should mean that when we come into say an example like this one and i know it says without flex grow we're going to get to flex grow in a second but say we come into example like this one and i come on to my flex parent and then i say dot flex parent and we do our trick like this and we say flex basis of 100 and they're going to all match the same size so this is the exact same thing that's coming in what i'm doing is i'm overwriting that default that we had on them so their their default size was their content size we're now saying it has a flex basis or a width of 100 percent so flex basis 100 so it wants to now be 405 and that this depends on the screen size so if i adjust that you can see it's going to change depending um so it's taking the width of its parent because a width of 100 means look at the parent so it's taking the parent's width but because they all have a flex basis of 100 that means they all want to be that size so it's just taking that size divides by three and all of them shrink by the same rate so they all end up being the same size uh let's just close the dev tools for a second and this also works when we just do our flex of one it's gonna look identical they're all just taking up the same amount of space but it's doing it in a really really different way and it's the reason why the flex one doesn't work here when we tried it let's do it uh even columns flex one there we go and remember they're a little bit off in size but it's doing its job it's just not getting us all the way there let's go just go back to here for a second and one of the reasons it's happening is because people is because what the flex shorthand is doing so the flex uh the flex shorthand is actually short for three things and the default is actually zero one auto so auto is sort of that what's making it behave with the max content that max content behavior where it's looking at the content size the flex basis is getting set to auto it also means if you set a width the flick this will sort of look at the width but if there's no width set then we go to the content size but so this would be a flex grow of zero a flex shrink of zero of one sorry not and then a flex flex basis of auto right there and this is what the default is so you can see up here it looks exactly the same what's interesting is when we use the flex shorthand so you do a flex of one you would think it would we're we're just setting the first one and we're ignoring the next two values so you'd think what that would do is actually set this where it would make a flex grove one look they fill up that space and just like here with with my flex pro the one is filling up the space and that works exactly like the flex shrink works it's setting the content size so it's looking there and let's go look in the dev tools again i love these dev tools so it's looking at the content size of 70 and it goes oh well i have a lot more the parent is a much bigger we have all this empty space it takes that empty space and it looks at how much is available and it distributes it and everything grows at the same rate to fill that available space and then they all end up in this case all with the same final size because they all have the same content size and the flexibility is on there for them to grow but the thing is that's not what flex 1 does flex 1 actually does this did you know that it changes the flex basis um and if you don't believe me let's just turn this off and go and take a look at it and do an inspect and look at this with a flex one the content size is zero and you can also see this by going on this side here if you can find your flex one and you can expand that in your dev tools and it shows flex grow as one flex shrink is one and flex basis is now zero that's a really weird thing that when you admit the when you omit the flex basis that it's actually setting it to zero percent and that's why the flex grow has to be on in this case because what it's saying is all of them want to be zero pixels and then because flex grow is available they're all going to shrink it's a little bit the opposite of when i use the flex basis of 100 so i'm trying to make them all really big and then they're shrinking to fit the available space in this case we could turn off like shrink and nothing's even gonna happen because they're all super tiny they have a base content size of zero and they're growing to fill the space so it's two opposite approaches but they end up pretty much with the same solution but as we saw from the beginning the solution is not perfect so what's happening when the solution isn't perfect like this it's happening for a bit of a weird reason and once again the dev tools will help us take a look and i'm going to go actually let's look at this one so the content size is zero because we're using a flex one but what's interesting with that one is if i go on to my card here and actually i'm just going to make these a little bit bigger so they're back to there just so these numbers are what i want them to be and what's interesting is we look at our call and our card and our column here they're actually all coming up with the same flexibility of 189.33 because that's the available space and that's kind of weird why is it 189.33 my parent has a width if we find the parent even columns has a width of 600. so if they're all shrinking down to zero shouldn't they be growing by 200 each because i made up two four six hundred hmm that's kind of weird but you can see that and this card is clearly bigger than these other ones but it's saying that it's growing by the same amount and its final size is the same what why is that happening okay so this is one of those weird things with css but it's really good that it happens because if not flexbox would be unusable and you'll notice here it's looking at the content size so if you think back to your box model days you know when you first started learning css the box model is your content box then your padding box your border box your margin box so the content size isn't looking at your padding or your border and we never really look at the margin but you know i'm sure everybody does this reset where you're setting your box sizing to border box on the stuff that you're working on because you want your padding and your border as part of the width but flexbox doesn't look at those and that's for a really good reason because imagine if when we're growing and shrinking our items like this the padding was growing and shrinking with it like you could have a border that you have a two pixel border that would literally disappear into nothingness as it shrunk down that could be really problematic and cause a lot more problems than anything else so that's why flexbox only looks at the content size so what's happening here and the way it's figuring this out is everything is getting shrunk down to zero uh let's just make this bigger because the numbers are much easier to work with so everything is shrinking down to zero but this card on it has some padding on it of one ram so one ram it's 16 pixels on both sides so we have 32 pixels of content so when it's deciding how much space it has to distribute it's doing 600 minus 32 which is 568 i think so we're now distributing 568 pixels of space and not the full 600 so the content size of each one is becoming 189 and it's 189.33 and then on this middle card here we're then adding the padding back on top of that and as i saw like this would be something you might expect if you don't do this on it with the border box because that's sort of the default behavior that we grew up and loved a long time ago with css that we no longer deal with but this is what's happening with flexbox now what's also really interesting here is the reason that things are different when it's hard to work in this screen space with the dev tools open um but it's also the reason that when i did a flex basis 100 not 10 100 percent when we do a flex basis of 100 we saw the numbers here on the split they're not the same but they're closer than what it was and that's because as i said it's the exact same thing as the flex one but it's the opposite a little bit we're trying to make them really really big and then shrink them down so the whole reason that it's coming out to a closer number is that 32 pixels of padding has a smaller influence because it's such a big number that's getting divided by because we're now looking at a base size of 568 plus 568 plus 568 so it's taking that times three then it's minusing the 32 and then it's dividing that space so just the 32 pixels has a much smaller influence on 1500 or 1600 or whatever than it does on the 600 pixels we were working or the 500 and whatever pixels we were working with the other way around so in both of these situations it's not working ah that's annoying so how do we fix it there are different approaches and i used to be a very big proponent of just sticking with flexbox and there's a flexbox solution that we'll see in a second but what my my my new solution is is deleting this whole thing here coming up on here changing this over to grid and you're going well it's grid you know this isn't a two-dimensional layout kevin what are you doing but bear with me uh we can come on here and say grid auto flow is column and then we're going to get three columns just like that and you can see they're they're not quite equal spacing even it's a little bit weirder because the two outside ones are different sizes so kevin this isn't working what are you doing ah but then i can do a grid auto column is one fr and now once that updates i know i have no changes and you have to remember this is called the column or columns is really annoying when you're doing this auto stuff but there we go now we have 200 200 200 they all match each other and the reason that i prefer this over a flexbox solution which we'll see in a second is i love that this is all on my parent and that i'm explicitly controlling it all on my parent and the 1fr here is the saying they're all equal basically take all the space divide it up equally for each column and make it work and you might be going well you know this is what if i you know at small screens it obviously breaks you change your flex direction a lot of the time right so well you could easily grab these two guys here do an at media min width is we'll go pretty small on this 30 mm and then we can say our even columns throw that in here and now when we get to small screen sizes they will stack and then we'll get to these screen sizes that go next to each other because we're switching the auto flow direction and the default auto flow direction is row so that's why i'm not explicitly putting it here but if you wanted to put it you could and this is another thing i really like compared to flexbox with flex direction flex direction makes sense once you think about it but when you're first learning flex direction the fact that a row makes columns and columns makes rows it's kind of weird and it makes sense once you think about it but this makes sense without even having to think about it i declare column i get columns i don't i declare a row and i get rows that just makes sense to me so i think as a beginner learning that becomes a lot easier and then of course if you don't want to bother with the media queries you can use your repeat autofit and other things like that and there's other solutions to this as well that are kind of similar to using flex wrap they're not exactly the same um so yeah just throwing that out there that there are solutions like that that could work now i did promise also a flexbox solution so let's undo all of this and get to the flexbox solution and this will work whether you do the flex basis 100 or if you use the flex one they both have the same um finish and what it would be are the same finish the same the same effect here i would just come in with a div dot call and we can drop that over here and now if we do that there we go they all have the same spacing and this is you know my card here sort of gets weird because now it's not matching the height of its siblings because it's not a flex item anymore and this is working because the padding is on the card and not on the column itself so now the whole card including its padding is part of that content and we've really been hammered home with this like type of design pattern because of the float based layouts we used to have to do and then we only had flexbox so this is how we had to work but one of the reasons i love grid is because i think that the grid solution is more intuitive and it allows us to have simpler markup why do i have to have a card inside my column and i can't just have my card as a column uh you know i can just plug and play content wherever i want with the grid solution and also i think that it's a lot more intuitive and you can still follow the same pattern if you prefer this pattern you can still follow it with the grid solution but i think that the grid solution is also more intuitive with the flex direction control that you have and it also makes it easier to use with grid you get so much control it's also not to say that flexbox doesn't have its use case anymore if we go back to our super basic example we're relying on items with their intrinsic widths of this max content think of a navigation of buttons that you need to go next to each other of things like that that's flexbox shines and it makes even spacing of things so easy uh that are different widths from each other which is kind of hard to do or impossible to do with grid depending there's ways of getting intrinsic widths uh with grid but it's you know i just think that flexbox that's where it's really shining and then grid when you need these more rigid structures that's where it's really shining so personally i'm no longer thinking of grid and flex boxes like a 2d 1d type of thing i'm thinking it more of do i want ultimate control over this or do i need the content to have an influence on how the layout is like a grid i like my navigations where some items are longer and some items are shorter and different situations just like that one of the nice things is you get to choose which one you like better as long as you really understand how to set it up and how to use it and if you really enjoyed this video and you like deep diving topics in css like this i set up a custom playlist for you right here that you can go and check out where i'm deep diving a few different topics and with that a really big thank you to bozak and randy who are my supporters of awesome over on patreon as well as all my other patrons for their monthly support and of course until next time don't forget to make your internet just a little bit more awesome
Info
Channel: Kevin Powell
Views: 88,032
Rating: undefined out of 5
Keywords: Kevin Powell, css, front-end, frontend, html, tutorial, flex, flexbox, css flexbox, flex-basis, flex shorthand, how flexbox works, using flexbox, flexbox vs grid, css grid, css flex
Id: fm3dSg4cxRI
Channel Id: undefined
Length: 22min 42sec (1362 seconds)
Published: Thu Jun 10 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.