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.

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:

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):

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):

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.

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.

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.

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.

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)

[…] 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, […]