The Flexible Box Layout module (commonly referred to as FlexBox, for convenience) is implemented in Firefox, Chrome, Safari, and IE10 (Platform Preview, at least). I wrote an article explaining FlexBox in detail in .net magazine last year, but thought it worth following up with a short, practical guide on a few things it’s useful for.
I actually don’t think it’s perfectly suited for complex page layouts, but it does some simple things very well, so that’s what I’ll concentrate on. There are three use cases in this article, none of which are impossible using CSS2.1, but all of which are made easier with FlexBox.
You can see all of the examples in action on this page: Demo: Three Practical Uses for FlexBox — it should go without saying that you’ll need to be using a decent browser.
Equally-distributed Navigation Items
For the first example I’m going to make a horizontal tabbed navigation, where all of the tabs have equal widths and spacing. In my example I have four tabs inside a parent which is 600px wide, each tab has a 1px border, and between each of the tabs I have a 4px gap. I can set the tab widths by using absolute numbers or percentages* but both of these mean making calculations, and having to recalculate when new items are added — not practical if you create a website for a client with no knowledge of CSS.
Using FlexBox makes this much easier; you just need to give the list parent a display value of box, and each item a box-flex value of 1:
ul.nav { display: box; }
.nav li { box-flex: 1; }
Of course, you will have to use all of the prefixed properties (–moz–, –ms– and –webkit–), but these are the core rules. What this does is distribute all of the li elements equally into the parent, after margins have been accounted for; no calculations required, and no modification of the CSS needed if an extra nav item’s added.
Update: As pointed out in the comments, if you have very varied text in the list items this actually doesn’t work the way you think it should (especially in Firefox), as the widths of the tab will vary to fit the content. To work around this in WebKit browsers you just need to add a width value other than auto; even 0 is acceptable. In Firefox you need to add a greater width value (in my example I’ve used 150px which, as there are four children, is 25% of the parent) just to get the layout working in the first place, and there is no way to stop the tabs from resizing.
Vertical Centring
Horizontal centring is easily achieved by using an auto value for margin-left and margin-right, but vertical centring is not so easy; there are a handful of different methods, but they involve either extra markup, or a fixed height on the centred element, or both. FlexBox does away with those drawbacks.
In this example I’m going to centre an element horizontally and vertically inside it’s parent, using these rules:
.parent {
box-align: center;
box-pack: center;
display: box;
}
.child { box-flex: 0; }
The box-align and box-pack properties control the distribution of unused space on the horizontal and vertical axes (respectively), so giving them a value of center means all space will be distributed equally on all sides, positioning its child in the dead centre. The box-flex value of 0 on the child element just means it will retain its set dimensions and not be resized.
Start and End Alignment
In my third example I’m going to use a fairly common design pattern, which is two elements positioned at opposite ends of their parent, on the same axis. This is quite often seen in headers and footers, and the way to do this currently is using either absolute positioning or floats; both involve setting dimensions, so aren’t very flexible.
With FlexBox this can be done with the box-align property we saw in the previous example, but with a value of justify:
.footer {
box-align: justify;
display: box;
}
.footer p { box-flex: 0; }
The two p elements in the footer have the box-flex value of 0 so retain their dimensions, and are displayed justified in their parent — that is, one at each end of the .footer element. Note that this value doesn’t work in Firefox’s implementation of FlexBox; hopefully that will be resolved in the near future.
Wrapping Up
So can you use FlexBox on your sites today? I think so, if you take care; you can detect support using Modernizr, and provide fallbacks for incompatible browsers. A couple of things to bear in mind, however: first, Firefox’s implementation is quite old and not quite in sync with the spec, as well as having some bugs (I intend to write more about that in a future post); second, the syntax is going to change in the future, and perhaps behaviour will change slightly too.
You can read about the new syntax in the latest version of the spec; I know the WebKit team are implementing this right now, so it may appear in the very near future. But these prefixed properties should be supported for a while to come, so it’s reasonably safe to use them, in my opinion; although perhaps not if you’re going to hand the site over to a client and never touch it again.
What you call Flexbox, which seems to be the CSS standard they’re trying to implement, I more often see as “Flexible Box Model.” And then there is a popular jQuery plug-in that is called FlexBox. Could be confusing to readers.
Totally agree that the flexible box layout model is not great for full-page layouts but good for individual areas of a page. It’s great to see ideas for practical use – thanks!
However, your first example of equally sized navigation tabs won’t work. Setting the box-flex value to 1 on all the tabs will not make them all the same size – try putting a really long word in one and a really short word in another and you’ll see what I mean. It’s hard to explain briefly; I explain in fully on pages 248 – 250 in my book Stunning CSS3.
This is a common misconception with the box-flex property, one that I think is mostly to blame on the spec – it should be clearer, and the definition is not intuitive.
Hi Zoe, thanks for your comment.
I see what you mean; this is certainly the case in Firefox. In WebKit you can give any width value other than auto (even 0 is okay) in order to make the widths equalise. I’ll test it in IE10 and see what the result is there, and I’ll update my post later to make sure this is clear.
I made my recent relaunch with flex box layout — as a full page layout. This was not that bad at all. I would not say flex box is not good for full page layout.
Especially I had to consider accessibility issues — it was a little bit tricky to get flex box right for page & text zoom. And in combination with media queries it was quite a perfect solution.
And if flex box attribute box-lines is fully supported you can get a real flexible box model running.