It’s hard to sum up all the awesome that is flexbox in a little ol’ blog post. Although we gave it a shot here. Here, let’s just try and focus on one thing that flexbox solves very nicely: the ability to have an arbitrary set of boxes fill up all the available height of a parent box. And not only that, but expand beyond that if needed (not squish them to fit).
By “box”, I just mean block level element. Div, section, article, whatever.
By default those boxes height is determined by the content inside them. They will stack on top of each other. Their parent boxes height might also be determined by their height combined, but it could be different (e.g. it’s set explicitly or it’s something variable like the browser window). If the parent box has a larger height, there will just be empty space below.
Can’t we force the boxes to split up the space evenly amongst that space? We can with flexbox.
Say the HTML is like:
<section class="fill-height-or-more">
<div>
<!-- stuff -->
</div>
<div>
<!-- stuff -->
</div>
<div>
<!-- stuff -->
</div>
</section>
Then we kick off flexbox with the parent box:
.fill-height-or-more {
display: flex;
}
and make the boxes up-and-down (column) rather than left-and-right (row) as is the default:
.fill-height-or-more {
display: flex;
flex-direction: column;
}
With just that, it will look no different than it did if we did nothing. But now we apply the flex property to the children and they will fill the space:
.fill-height-or-more > div {
/* these are the flex items */
flex: 1;
}
Annnnd done =).
As a detail here, flex: 1;
is the same as saying flex: 1 1 auto;
It is shorthand for three different properties:
flex-grow: 1;
flex-shrink: 1;
flex-basis: auto;
Just so happens that giving them the ability to grow on an equal basis the most common need so flex: 1;
is a nice way to write that.
One of the nice things about flexbox is this will work with an arbitrary number of boxes. Could be a single box! Could be 100 boxes! Doesn’t matter. If there is extra room, the space will be divided and filled. If not, no big deal.
In a pre-flexbox world, we might have tried to know/find out how many boxes there were, and then set their heights with percentages. That works to fill extra space, but if there were too many boxes, you’d get squished. That’s another nice thing about flexbox, it won’t squish those boxes to the point of them not being able to fit their content. So…
If we wanted to take this a step further, we could use flexbox to center the content within those boxes too (!). This is where people get mad at CSS though. Vertical centering is kinda hard. Even with flexbox here, we’ll need to make each of those flex item children we have into flex containers as well. Then use an internal wrapper which becomes the flex item we center. So yeah, an extra element still. Update: Tedmotu did it without the extra element, which is really straightforward
To center it, we make the direction up-and-down again (column) and use another flexbox property, justify-content
, to center it.
.fill-height-or-more > div {
flex: 1;
display: flex;
justify-content: center;
flex-direction: column;
}
This is where the reference guide comes in handy… finding out which property does what quickly.
Then we get this:
See the Pen Boxes That Fill Height (or more) by Chris Coyier (@chriscoyier) on CodePen.
Browser Support
I’ve only used the latest syntax here in this post. Current versions of Chrome, Opera support it just like that. Near-future versions of Firefox and Android will be supporting it just like that as well. Safari and iOS support the new syntax, just with -webkit- prefixes. Can I Use has the whole story.
IE is weird. IE 10 supports the tweener version of flexbox (e.g. display: -ms-flexbox;). IE 11 supports the latest flexbox. With this particular demo though, something is broken. While the height of .fill-height-or-more renders at full height by using min-height
, the boxes are squished.
If you use height instead of the flex container, it “works” – but the point here was using min-height to avoid squishing. Seems like an implementation bug to me.
UPDATE: Nirav Zaveri wrote to tell me that in IE (I tested v11), flex: 1
isn’t the same as flex: 1 1 auto
, even though it should be (?). If you set the later, it works.
It’s understandable that you might need to go back a bit further with browser support. Firefox 27, iOS 6, and Safari 6 are pretty legit browser support targets and all those use some variation of the older syntax, sometimes prefixed and sometimes not.
Just our little example looks like this when as fleshed out as it can be for support:
.fill-height-or-more {
display: -webkit-box;
display: -webkit-flex;
display: -moz-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-webkit-flex-direction: column;
-moz-box-orient: vertical;
-moz-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
}
.fill-height-or-more > div {
-webkit-box-flex: 1;
-webkit-flex: 1;
-moz-box-flex: 1;
-ms-flex: 1;
flex: 1;
display: -webkit-box;
display: -webkit-flex;
display: -moz-box;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: center;
-webkit-justify-content: center;
-moz-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-webkit-flex-direction: column;
-moz-box-orient: vertical;
-moz-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
}
Yeesh. My recommendation? Write it in the modern syntax like I have above and let Autoprefixer deal with it, which not only deals with the prefixing but the older syntax as well.
Video Screencast
Might as well hey? I published it here and I’ll embed it also:
Oh and just for the record, the real-world scenario that brought this on for me was this page.
Sweet write up! I love flexbox. I even built my personal site just using flexbox.
Can’t wait to be able to use it in production sites in 2020. :(
Ah, an optimist.
I’m curious if flexbox could be the solution I have been trying to work out. Scenerio is you have two columns of content. Column A is feature image of a blog and Column B is the preview text. There are times that Column A will be blank so Column B fills out the whole space.
If Column A uses an optional
img
you might want to look at the:empty
pseudo-class:.col-a:empty { display: none; }
MDN Docs
Wow. This is the most timely blog post I’ve ever read. Just this morning I was trying to solve this exact problem. Thanks Chris!
Rather than use the excess flexes to vertically center in one of my projects, we used the following method. It works nicely :) http://zerosixthree.se/vertical-align-anything-with-just-3-lines-of-css/
I’m also a fan of the translate centering, but you need a single element in which to perform that transform, so kind of a horse a peice.
I’ve been on the flex bandwagon for about six-eight months now and cannot wait for it to be ready for primetime. As of writing, we’re still having trouble with Safari (align-self wasn’t supported until late last year), Firefox (flex-wrap is still not supported in public version until April) and obviously IE8 and 9.
Really, really looking forward to the day when we can use flex without fallbacks. I read a tweet the other day which said that once you used flex you’ll never feel right about laying out pages another way and I totally agree!
That’s so sweet.
But you know the bummer: IE.
Even IE9 can’t help you here.
Great as always, thank you for the tip Chris.
Flexbox might well be awesome if we could use it. In the real world, IE8 still has far too much use to rely on flexbox for a world-facing site. Net Applications (the people Microsoft trust for ie6countdown) give IE8 >20% worldwide in December 2013; StatCounter has always had a much lower stat, but still says 6.6% (and another 3.9% for IE9, oddly; I’d’ve expected those people to be on IE10 at least by now). E.g., more than 10% without flexbox even by the lowball estimate, far too much traffic to ignore.
(And IE8 will be here for some time to come, thanks to Microsoft’s mind-numbing refusal to release a modern browser for XP, while continuing to support XP for volume license customers — read: large corporations and governments — throughout the lifecycle of Windows 7.)
It’s fantastic that MS are finally onboard the “keep the browser up to date” bandwagon. Now if we could just get them to do what all the other vendors do and support their browser on XP (since they can’t change their minds about the volume agreements)…
Remember which stats matter: YOUR site’s stats.
If I was building an eCommerce site that sold gardening equipment, I’d probably make that thing work back to IE 6.
When I do my next design refresh here on CSS-Tricks, I’ll probably use flexbox and have an IE 10 minimum.
(Replying to myself because there’s no ‘reply’ link on Chris’ comment)
And what stats do you use when you’re creating something new? Average stats matter.
Why an extra div element?
No need for that. The ‘justify-content: center’ should suffice, and if you want cross-axis to be aligned as well, you do ‘align-items: center’.
Any box which has these two styles will have perfectly centered children. They don’t need a dummy parent.
I couldn’t get that to work. Feel free to fork it and remove the element and get it centering. I’d love to update the article to be even cleaner.
Fork (no extra divs)
I’m using chrome 32, and the above pen looks the same to me as your pen. Maybe I’m missing something?
I usually prefer flexbox for aligning specifically for this feature – it allows me to align sibling element with no dummy wrappers.
That does work! Dammit why was I having so much trouble? Anyway I updated the demo and I’ll make a note in the article.
Flexbox, kickin’ ass.
Flexbox is indeed awesome :)
For my current project i am also working with flexbox. It solves a lot of CSS layout problems and enables us to layout “web application ” style. I have to admit that i am still not really used to it, always peeking on the usual demos.
I recently tried to align web-card-style objects in a grid with flexbox. My idea was: If there is only one item, it’s in the middle (vertically AND horizontally // aka holy grail). then it fills up. each row can have three items, there can be multiple rows.
My problems started with the second row (using flex-wrap: wrap): i had problems aligning a three by three grid equally (horizontally and vertically with “space-around”). Also for the second row the center property looked weird. first row with three items, second row with two horizontal centered items, hm. tried all kind of obscure hacks (like nth-child) and finally gave up.
@Chris: Your example here is as usual nice & easy. Maybe i go with this instead. On mobile there are no columns anyway.
But i would be curious to know if there is a codepen example out there showcasing something like the above in both axises (x & y).
Your example actually works as it is on Firefox 22+ as well. What Firefox doesn’t support yet until 28 is flex-wrap and flex-flow. So, if you don’t feel you need these, and need to make a decision on whether to implement flexbox, count Firefox users amongst the “pro using flexbox”-group.
The issues with this and IE10/11 caught me out today, and you’re quite right Chris that this looks like an implementation bug from M$.
https://connect.microsoft.com/IE/feedback/details/802625/min-height-and-flexbox-flex-direction-column-dont-work-together-in-ie-10-11-preview
Anyone willing to go through the rigmarole of registering for the MS Connect site and +1ing this bug would be greatly appreciated.
Hm, that’s frustrating. Anyone have a good workaround for growing to fill a container in IE10?
Chris,
This doesn’t seem to work inside a table-cell element. See this example: http://jsbin.com/xexojefu/2/