Three Practical Uses for FlexBox

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.