Equal Height Columns with CSS Flexible Box Layout

CSS3.Info today published a guide to the Flexible Box Layout, one of the modules of the upcoming CSS3 specification. The Flexible Box Layout provides a way of utilizing unused space in containers by specifying either a horizontal or vertical layout. After the children of element are rendered, any spare space will be divided up equally (or for that matter, in any ratio) between the child elements.

This essentially provides the kind of fluid layouts that you can construct with tables, without actually using tables. It already has support in Gecko and WebKit based browsers through the -moz and -webkit prefixes and with some tweaking, we’ve found a solution to the age-old problem of equal-height columns.

We start by creating a <div> tag with the ID “container”. We style that in the following way:

#container {
display: -moz-inline-box;
-moz-box-orient: horizontal;
-moz-box-align: stretch;
}

This tells the browser to use the required box layout, to orientate the children horizontally, and to stretch them if the combined width is less than that of the container.

Inside, we’re going to put three divs and style them as such, using a parent child selector:

#container div {
 -moz-box-flex: 1;
 border: 1px #666666 solid;
 margin: 5px;
 padding: 10px;
}

It’s only really the “-moz-box-flex: ” property that needs to be set. The margin and padding are for presentation, and the border around the edge is to demonstrate that the boxes will scale.

To set up our traditional left and right-hand-side columns, we need to add a “min-width: ” property to them, like so:

<div style="min-width: 100px;">Left-hand-column</div>
<div></div>
<div style="min-width: 100px;">Right-hand-column</div>

We can now add as much content as we like to the central column (or any of them for that matter) and the others will scale to whichever column is the tallest. See an example page here.

Things Worth Noting

In the above code, I’ve just used the -moz prefix for conciseness. For WebKit compatibility, just duplicate any prefixed lines and change the -moz prefix to -webkit.

By using this layout, you’re essentially making the container <div> an inline element, which means certain properties you would normally apply to it, will not work. In the example page, I’ve added a<div> around the container with the “margin: ” property set to “0 auto” in order to center in the page.

Because we’re handing over the sizing of the child elements to the Flexible Box Layout, we cannot control them using the “width: ” property. Instead, we can size our columns with the “min-width: ” property.

Finally, for some reason Firefox does not accurately represent the padding on the column that is causing the expansion. This is evident on the example page, where the central column has padding on the top and left but not on the right and bottom, despite it being declared in the CSS.

  1. Great demo. I did discover something unexpected, but this specification seems to conflict with the “column-width, column-gap” specs. I tried to make the center column in your layout flow multiple columns for the text. The column-width attribute directly affects the width of the flex width.

  2. Yeah, you’re right Joel. That is a bit of pain, but I’ve found that it’s only the “column-width: ” property that causes the problem. If you use “-moz-column-count: ” and “-moz-column-gap: ” together, you can achieve the same effect.

  3. Hi Andy,

    Will be interesting in the coming months to see which offers the best real-life use: columns, or the flexible box model. This is a great, simple example we can use to inform that thinking – thanks!

    BTW, the padding looks fine to me on that middle ‘column’ (FF3.5.3).

    - Bobby

  4. Hmmm, something strange going on clearly. FF 3.5.3 on the Mac is still showing no padding on the bottom for me. The Alpha 1 of 3.6 renders it perfectly though, so it’s obviously being addressed.

    I think the two areas, although similar, serve two different purposes. The great thing about the columns model is the way the text flows through the columns and the great visual effect that comes from having these columns both top- and bottom-justified. This is more to do with content overflowing vertically, but everything adjusting vertically with it.

  5. OK, I should have scrolled down and read more carefully ;-) Padding definitely present on the right, on Windows, though.

    • foo
    • October 17th, 2009

    why do you need the extra div to make it centered?
    Couldn’t just put a width and margin auto on the display:box div?

  6. Divs are normally block-level elements, but setting the display to -moz-inline-box or -webkit-inline-box changes that element to an inline one. You can’t use the auto value for margins on inline elements, so you need a regular block-level on the outside to compensate.

    I haven’t fully checked the spec to see if it’s right to convert it to an inline element, but judging from the name of the property and the fact that it renders this way in both Webkit and Gecko, you’d assume that it’s correct.

  7. Other variant is possible also

  1. No trackbacks yet.