CSS3 Flexible Box Layout Module (aka Flex Box) introduction and demos/test cases
Doing layouts on the web has always been hard, but it seems like we’re getting a better option to do it now.
Background
First, we had tables
for layout, and while semantically incorrect, with proper nesting and other tricks, we could build fairly functional layouts with them.
Then along came floats
which most of the people are using today. We can use any element we want to, but floats
aren’t really for the fainthearted. On surface it seems pretty basic, but the complex functionality behind can make seasoned developers look dumbfounded at their screens. Also, one of the downsides with floats
is needing to clear them through extra clear
elements or, better, clear CSS floats without extra markup.
Downside with that, though, besides from it’s not that easy to grasp floats, is that we need various trickery to support equal-height columns, since there’s no default way to set up a relationship between elements with floats
.
Then some people have started using display: table
, display: table-cell
etc, but since support took so long to get in Internet Explorer (IE8), people seemed to give up on it and just accept floats as the de-facto solution.
Introducing Flexible Box Layout Module (aka Flex Box)
One hidden gem that most people seem to have missed is the Flexible Box Layout Module. It offers:
- Equal-height columns.
- Source-order independence for elements.
- Specifying a relation between elements.
- Flexible size and alignment of content.
A simple example
Let’s say we want to display three columns next to each other. It would then look like this:
<div class="flex-container"> <div class="col-1">I am column 1</div> <div class="col-2">I am column 2</div> <div class="col-3">I am column 3</div> </div>
.flex-container { display: -moz-box; display: -webkit-box; display: box; -moz-box-orient: horizontal; -webkit-box-orient: horizontal; box-orient: horizontal; }
We’re using the display
property to set the containing element to a box, and then we use the box-orient
property to set it to be horizontal
(you could also use vertical
).
With this approach, the direct child elements (i.e. <div class=”col-1″> etc) will be laid out next to each other, with their width set to their contents. But what if we want them to together expand out the entire parent width, in a flexible manner? Then we need to apply box-flex
to them:
.col-1 { -moz-box-flex: 1; -webkit-box-flex: 1; box-flex: 1; } .col-2 { -moz-box-flex: 1; -webkit-box-flex: 1; box-flex: 1; } .col-3 { -moz-box-flex: 2; -webkit-box-flex: 2; box-flex: 2; }
The value of the box-flex
property is about how the remainder of the width is divided by the elements, as explained in Zoe’s comment, where a larger number means wider. It also means that each element can afford having a padding, which won’t make them become too wide (great, right?).
Setting presentation order
We have two ways of setting presentation order, which is through the box-direction
property on the parent element (i.e. the one with the display: box
property set), or we can use box-ordinal-group
to give each column/child element a number which is in the order they will be visually represented (interestingly enough, in Firefox this also aligns the elements to the right, but in Google Chrome and Safari they are to the left):
.flex-container-reverse { display: -moz-box; display: -webkit-box; display: box; -moz-box-orient: horizontal; -webkit-box-orient: horizontal; box-orient: horizontal; -moz-box-direction: reverse; -webkit-box-direction: reverse; box-direction: reverse; }
meaning they are presented in a reversed order, or:
.col-1 { -moz-box-ordinal-group: 2; -webkit-box-ordinal-group: 2; box-ordinal-group: 2; } .col-2 { -moz-box-ordinal-group: 3; -webkit-box-ordinal-group: 3; box-ordinal-group: 3; } .col-3 { -moz-box-ordinal-group: 1; -webkit-box-ordinal-group: 1; box-ordinal-group: 1; }
where col-3 is presented first, then col-1 and finally col-2 at the end.
Centering and justifying
We have another interesting property, box-pack
, which we can use to specify how the boxes should be presented, e.g. centered, justified etc. This would center the three of them within their parent element (interestingly, the previously set padding
now disappears):
.flex-container-center { display: -moz-box; display: -webkit-box; -moz-box-orient: horizontal; -webkit-box-orient: horizontal; box-orient: horizontal; -moz-box-pack: center; -webkit-box-pack: center; box-pack: center; }
We could also justify the three elements evenly within their parent:
.flex-container-justify { display: -moz-box; display: -webkit-box; display: box; -moz-box-orient: horizontal; -webkit-box-orient: horizontal; box-orient: horizontal; -moz-box-pack: justify; -webkit-box-pack: justify; box-pack: justify; }
However, justifying only seems to work properly in WebKit-based web browsers (Google Chrome and Safari).
Flexible Box Layout Demo
As part of my ongoing CSS3 test suite, I have added a number of CSS3 Flexible Box Layout Module examples and test cases, where you can see the tests in your web browser, the code being used and also the possibility to change it and see what happens.
Web browser support
- Firefox 3.0+
- Google Chrome 5.0+
- Safari 3.2+
- iOS 3.2+ (Mobile Safari)
- Android 2.2+
That’s a pretty good web browser base, but unfortunately there’s still no trace of support in the beta of Internet Explorer 9 or beta of Opera 11, but I do hope it catches on there too, because we really need another alternative for creating layouts on the web.
[…] document.getElementById('fb-root').appendChild(e); }()); Another great writeup by Robert Nyman: CSS3 Flexible Box Layout Module (aka Flex Box) introduction and demos/test casesAbout this entryPublished:Dec 02 2010 / 3:42 pmCategories:ElsewhereComments:No comments Jump to […]
Good article. For the sake of readability I would have presented the normal properties only in the first examples, and their vendor-prefixed equivalents after that.
Florent,
Thanks! And it’s interesting that you mention that, since I did it this way on purpose. My experience with blog posts is that if you have code in them, even only as a part, people copy that and then have problems getting it to work (I’m that way too 🙂 ).
Therefore, I always like to have all working code together, even if it seems a bit superfluous.
Nice write up Robert!
I did some experiments with flex-box during summer last year, and found the implmentations in WebKit / Gecko to be just too different to be able to do anything meaningful with it without so many hacks that float seemed trivial.
Glad to see things moving along.
Here’s a related project to extend Flexible Box Module to non-supporting browsers. Version 1.0 should be out soon.
https://github.com/doctyper/flexie
Morgan,
Thanks!
And yes, things have gotten a lot better, but still, you need to experiment with what you want to use and make sure it behaves as intended.
Micah,
Cool, thanks!
Very good article! I’ve recently test Flexbox : here my demo http://devlint.fr/labs/flexbox.html
As you, I wait for IE9 & Opera support as soon as possible 😉 !!
Webdevlint,
Great, thanks for sharing!
Very interesting article.
Thank you very much
[…] Robert's article: http://robertnyman.com/2010/12/02/css3-flexible-box-layout-module-aka-flex-box-introduction-and-demo… […]
Hi,
I’ve been playing with flexbox and created a simple layout scheme with pretty clean markup:
Fun with CSS3: Flexible Box Layout Module
Check out the .css file linked there for an explanation.
rodrigo,
Nice, thanks for sharing!
Great article overall, but your description of how box-flex works is inaccurate. (Every article I’ve read about flexible box layout makes this same mistake.). A bigger box-flex number doesn’t necessarily mean that block will be wider. The box-flex numbers affect the ratio of how the extra space in the box gets divided.
So let’s say your parent box is 600 pixels, child block 1 is intrinsically 300 pixels, and child block 2 is intrinsically 100 pixels. If you set box-flex to 1 on both child block, they’ll divide up the extra 200 pixels evenly, so block 1 will now be 400 pixels and child block 2 will now be 200 pixels. If you set box-flex to 1 on block 1 and box-flex to 2 on block 2, they’ll divide up the extra 200 pixels in a 1:2 ratio. So block 1 will get 67 extra pixels and be 367 pixels and block 1 will get 133 extra pixels (twice as many as block 1) and be 233 pixels. Thus, the larger box-flex value hasn’t resulted in block 2 being wider. It’s all about how the browser divides up the extra space (or overlapping space, if the blocks are naturally wider than the parent box).
Hope that makes sense. 🙂 I explain it better in my book Stunning CSS3, of course, since I have more room to do it justice.
Zoe,
Thanks! I’ve updated the post to reflect that.
Is it just me or
-moz-box-pack:justify;
doesn’t work? I can’t get any FF to render it in justify; even in the examples here, it’s not working, it just shows packed to the left. (I only have firebug as plugin, so there’s no conflict)Agustín,
Yes, it’s mentioned in the post. It only works in WebKit-based web browsers.
[…] talk ???http://robertnyman.com/2010/12/02/css3-flexible-box-layout-module-aka-flex-box-introduction-and-demo… […]
[…] value of the box-flex property is about how the remainder of the width is divided by the elements, as explained in Zoe’s comment, where a larger number means wider. It also means that each element can afford having a padding, […]
[…] talk ???http://robertnyman.com/2010/12/02/css3-flexible-box-layout-module-aka-flex-box-introduction-and-demo… […]
[…] ???Robert’s talk ???http://robertnyman.com/2010/12/02/css3-flexible-box-layout-module-aka-flex-box-introduction-and-demo… […]
[…] http://robertnyman.com/2010/12/02/css3-flexible-box-layout-module-aka-flex-box-introduction-and-demo… […]
[…] http://robertnyman.com/2010/12/02/css3-flexible-box-layout-module-aka-flex-box-introduction-and-demo… […]
Robert,
Great article!
I am very disappointed with the state of web development, as I tried to replicate my layout with html 5 (thanks to you, I am closer but still unsuccessful.
http://www.rhyous.com/2012/07/03/i-demand-a-simpler-css-for-html5/
We shouldn’t have to make the same setting multiple times for multiple browsers.
Rhyous,
Glad you liked it!
The CSS prefix situation is unfortunately something necessary at the time, for web browser vendors to be able to experiment before a syntax is finalized.
[…] ???Robert’s talk ???http://robertnyman.com/2010/12/02/css3-flexible-box-layout-module-aka-flex-box-introduction-and-demo… […]
[…] ???Robert’s talk ???http://robertnyman.com/2010/12/02/css3-flexible-box-layout-module-aka-flex-box-introduction-and-demo… […]
[…] CSS3 Flexible Box Layout Module (aka Flex Box) introduction and demos/test cases […]