CSS3 Flexible Box Model

CSS offers several tools to help with site layout. Over the years we’ve worked mainly with floats, positioning, and margins, but let’s face it, most of us would like more. Fortunately css3 is giving us more tools for layouts. One of those tools is the flexible box.Note: This post refers to an older and out of date version of the flexbox spec. A more recent post that refers to an up to date version of flexbox can be found here.

I’ve created a demo page illustrating some of the properties of the flexbox, though there’s not much to see in the demo that you can’t see from the images throughout this post. It’s there in case you want to play around with the source code.

Browser Support

On the other hand Opera as well as IE9 and below don’t support it so the flexible box isn’t yet ready for full time use unless you’re ok adding a javascript solution. Flexie is one such solution, though I haven’t had a chance to test it.

You should also know that the spec is changing. The latest W3C working draft and editor’s draft use different terminology than what currently works in practice. I’ll stick with the terminology that currently works and make note of the corresponding terms in the latest specs.

Also note that I’ll stick with the generic terminology in this post, but to make flexible boxes work in practice you’ll need to use vendor prefixes like -webkit and -moz.

Creating a Flexbox

Flexbox is a new layout mode provided by css3 and it’s similar to block layout on the surface. It lacks some properties of blocks such as floats and columns, but it adds some simple tools for aligning content inside a box.

In a flexbox content can be laid out in any direction, elements can be reordered dynamically, and the size and position of elements can flex in response to the available space.

A flexbox will act like a block when placed it other layout modes by default, but it can be set to act as an inline-box as well. Child elements of a flexbox are referred to as flexbox items.

Pretty simple to set up and again you need to use vendor prefixes at the moment.

display: -webkit-box

display: -moz-box

You’ll notice that horizontally we have 150px extra of space inside of the flexbox. Properties we later set on the flexbox items will allows us to modify this extra space and alter the behavior of the flexbox.

Note: In the current specs flexbox is being used instead of box so in time we’ll use display: flexbox.

Note 2: Once again the flexbox spec has changed and instead of either box or flexbox, it now calls for flex as in display: flex and flex-{*} for other properties.

box-orient and box-direction

box-orient sets the direction in which flexbox items will be laid out inside the flexbox and has several allowable values

horizontal — Lay out children from left to right in a horizontal line

vertical — Lay out children from top to bottom vertically

inline-axis — Lay out children along the inline axis (map to horizontal)

block-axis — Lay out children along the block axis (map to vertical)

inherit — The value will be inherited from the parent element

In the image above I set box-orient to vertical, which is probably the value you’ll set most often. Horizontal is the default.

box-direction is a more general way to set the order of the flexbox items. The one value to know about is reverse which displays the flexbox items in reverse order of how they’re listed in the html.

Note: It looks like both box-orient and box-direction are becoming the single flex-direction in the current working drafts.

flex-direction will have the associated values lr, rl, tb, bt, inline, inline-reverse, block, and block-reverse. lr stands for left to right and tb stands for top to bottom.

box-pack and box-align

We won’t always want to fill up all the extra space inside a flexbox. We may instead prefer to have child elements positioned within that space, for example centered vertically or horizontally.

One property we can use is box-pack, which has associated values of start, end, center, and justify.

Start and end can ultimately be any of the 4 box sides depending on whether your flexbox is horizontal or vertical and which direction it’s items are laid out in.

1
2

.box {box-pack: center}
.box {box-align: center}

Assuming a horizontal flexbox with no reverse set, start refers to the left edge and end refers to the right edge.

Items would be packed against this edge with the next item packed against the first. Center packs things toward the center and justify packs toward the edges.

Another property for dealing with extra space is the box-align property. It’s values are start, end, center, and stretch, which work similarly to the same values for box-pack.

A new value here is baseline which says to set each flexbox item so their baselines align and then distribute the space above and below. The baseline can be either horizontal or vertical depending on the direction of the flexbox.

Note: The current spec refers to box-pack as flex-pack and box-align and flex-align.

box-lines

The box-lines property sets how the box handles content that overflows it’s size and has the associated values single and multiple.

single — All child elements will be placed in a single row or column (elements that do not fit will simply be considered overflow)

multiple — The box is allowed to expand to multiple lines, to accommodate all of its children

Note: box-lines aren’t mentioned in the most recent spec, but the editors draft refers to flex-flow, which looks to mimic box-lines. I also haven’t been able to get box-lines working in any browser I’ve tested in.

Flexbox Items

The properties above control how the flexbox itself behaves. We also have some properties to control how the flexbox items behave.

Only direct descendants of the flexbox are considered flexbox items. Children of flexbox items (grandchildren of the flexbox) are not also flexbox items of the same flexbox.

A new flexbox would need to be created for them to become new items of a new flexbox.

box-ordinal-group

box-ordinal-group controls the order in which the flex-items are displayed within the flexbox. The values of the box-ordinal-group property are integers.

Because span 4 is given a box-ordinal-group of 1 it will display before both spans 1 and 3, which have a box-ordinal-group of 2.

Span 2 doesn’t have a box-ordinal-group specified and so defaults to a box-ordinal-group of 1. Because span 2 appears in the html before span 4 and because both have the same box-ordinal-group, span 2 will display first.

The order the spans will be displayed is

span2

span4

span1

span3

This will solve a lot of the problems I talked about last week in regards to rearranging html boxes as we’ll have more control over the order the boxes are displayed.

Note: In the latest specs box-ordinal-group is being referred to as flex-order, though it will work the same way.

box-flex

box-flex sets whether or not the child items are inflexible or flexible and in the case of the latter, how. It tells the flexbox and flexbox items what to do with the extra space.

It’s values should be seen as fractions. An element with a box-flex of 2 would get twice the extra space as an element with a box-flex of 1.

There’s probably not enough support to use flexboxes in practice, though of course it depends on what browsers you need to support.

The good news is flexbox seems to be coming in the next version of IE. The bad news is we’ll have to wait for enough people to upgrade or use a Javascript workaround. I suspect Opera will get on board soon enough.

I’m not sure that flexbox is ready for prime time yet either, but it’s closer than many things.

The difference between the current working draft and the editors draft are minimal. We’re talking display: box to display: flexbox. Most of the other differences are similar

I wouldn’t let those kind of changes stop you. A few quick search and replaces would be enough to fix things and there’s no way to know for certain when browsers would make the switch to any new terminology.

Also consider that you could still code a layout that won’t break if flexbox stops working. It would depend on where and how you use it. One application for flexbox is vertical and horizontal centering. Should your flexbox code stop working that probably doesn’t break the layout.

At the same time I’d agree it’s probably not the thing to use for client sites just yet. I wanted to explore a few things that are on the way, though, hence this post.

Right now, as of today, do you think we should do layouts this way? If so, why? Also, fallbacks, with Javascript, fine, but it could be done via IE conditional statements, no? Also does Opera support this or not? Furthermore, I heard that the draft or syntax is quite different. Do you think we ought to go for it and change it once it has been (or add it in this case).

I wouldn’t say we should use flexbox yet. I think it could be used, but at the moment there are the drawbacks you mentioned.

Opera and IE lack support, though you can take care of that with Javascript. I don’t think conditional comments would work since you’re layout would be very different for IE. You could try, but I think that would be too hard to work with. The spec is changing, though the difference in syntax isn’t hard to understand as I showed in the post.

For all those reasons I wouldn’t use flexbox just yet. I think you can use it if you don’t mind the workarounds, but for production sites it’s probably best to wait a little longer.

Having said that it wouldn’t surprise me if their are sites already using it.

Why Opera? Because if I am doing the site in HTML5 I still need Javascript for it to display for older IE browsers, so we have a saying here that goes, “if you are going to **** it up, do it all the way til the end”.

If the user has JS disabled, the site will not recognize the elements and wll look bad anyway. If he does, then the JS solution will work for both styling purposes and the flex-box model.

I think your decision makes sense. I really want to use it, but for now I think we’re better off waiting a bit more. I don’t worry so much about JS being disabled though. Many workarounds for css3 and html5 tend to be specifically for older versions of IE. I think the percentage of people with IE6 or IE7 and JS disabled is small enough to ignore, particularly for any site that deals with something technical.

As far as I know IE9 does not support flexbox by default. Only IE10PP seems to have built in support. You’ll need a workaround for IE9 and below.