Flexbox: CSS Flexible Box Layout

Do you remember when tables were the only layout method for a website? At least until people realized that it’s a semantic nightmare to misuse something that’s actually reserved to display tabular data for the structure of an internet site. So a new “tool” needed to be found and soon floats and absolute positioning were discovered as a “proper” replacement.

Just like tables, of course, the true purpose of these two methods wasn’t to give websites a shape. But nevertheless, here we are, over a decade later, and there’s still no reasonable solution for this “problem” – at least one that works a across a wide range of browsers.

But the chances are good that Flexbox (or “Flexible Box Layout Module” as the W3C likes to call it) is the next big thing. The latest versions of Chrome and Opera have already jumped on the bandwagon, Firefox will follow in version 20.

But be warned: there’s also an older version of Flexbox from 2009, which has pretty decent support, but was dismissed by the W3C late 2011 in favor of a more catchy syntax. To make things even more confusing there was a short transition period before that with an even more awkward syntax (you can read more about the phases here at CSS-Tricks). That aside let’s talk about the actual – and hopefully final – syntax of Flexbox.

The advantages

Some of the advantages of Flexbox (taken almost straight from the specs): Their contents …:

  • can be laid out in any direction (leftwards, rightwards, downwards or even upwards)
  • can have their visual order reversed or rearranged
  • can “flex” their sizes to respond to the available space
  • can be aligned with respect to their container or each other
  • all have the same height

To depict the various properties and possibilities let’s assume the following simple layout, which can by seen in its initial state here.

<div class="ex">
	<header/>
	<div.main>
		<nav/>
		<div.content/>
		<aside/>
	</div>
	<footer/>
</div>

The first step is to place the elements within <div.main> side by side, whereby the <nav> and the <aside> have a set width. Without Flexbox we’d probably float all the three elements (as seen in example 1), but run into problems at the <div.content> if we want it to take the remaining space. It’s possible with some trickery, but normally one would manually calculate its width. Moreover a dateless problem arises now: every element is just as high as its content. Therefore we would need to set an equal height for all three elements to get the same height or use one of the many tricks. Luckily things are much easier with Flexbox.

One note beforehand: Since Flexbox is still a pretty experimental property, vendor prefixes need to be set for Chrome (-webkit) and Firefox (-moz), Opera already supports the unprefixed version. To simplify things, I just use the unprefixed version throughout this article. Furthermore the functionality described herein is derived from Chrome, other browsers may vary (in the future).

Let’s flex

The core element of Flexbox is the new flex value of the well-known display property, which needs to be set for the container and transforms its children to so called “flex items”. These items adopt some highly helpful properties by default, on the one hand that they get placed side by side, where elements which have specified no certain width automatically take up the remaining space. So if display: flex is set for <div.main>, its <div.content> child is automatically squeezed in between <nav> and <aside> (since they have a set width). No more calculations! How handy is that? As a special bonus all of these three now adopt the same height (like seen in example 2).

.main {
	display: flex;
}

To ensure that flexed elements don’t exceed or fall below a certain width or height, the standard properties min-width/min-height and max-width/max-height can be used, as I’ve done for <nav> and <aside> with min-width (which is set to the same value as width).

The order of things

Another helpful property of Flexbox is the ability to easily change the order of elements. Let’s assume that you build the above layout for a client and she now wants that not the <nav> comes first but <div.content>. Normally you would dive into the HTML source code and change the order there. Not so with Flexbox. Just set the order property to -1 and it will come first (see example 3). In this case you don’t need to state the order for the other elements, but you could also do so and set order to 1 for <div.content>, to 2 for <nav> and to 3 for <aside>.

.main {
	display: flex;
}

.content {
	order: -1;
}

Unnatural placement

But your client isn’t satisfied yet. Instead of messing with the <div.content> she now wants the <footer> to come first, even before the <header>. Clients are crazy folks, you know. Well, Flexbox is also your friend in this case. Since we need to fiddle about not just at the inner elements but at the outer one the display: flex rule has to be stated for <div class="ex">. Since <header>, <div.main> and <footer> are stacked above we need to set a vertical context first, which is done with flex-direction: column. So if you ever want to change a row of elements into a column (or vice versa), you can use this property. Additionally the <footer> gets the order value of -1 as above so that it comes first. It’s as easy as that.

.ex {
	display: flex;
	flex-direction: column;
}

footer {
	order: -1;
}

All of this can be seen at example 4.

Proper alignment

Flexbox also makes it very easy to align its children horizontally as well as vertically. All the elements within a container can be aligned with align-items, individual ones with align-self. But the alignment of the elements is dependent on the set flex-direction. If it is row (that means the elements run in a horizontal line), the alignment concerns the vertical axis; if it is column (that means the elements run in a vertical line), it concerns the horizontal axis. To center the image within <div.content/>, for example, you need to set display: flex for this container first and then the flex-direction to column so that they get stacked atop. Finally the image gets centered with align-self: center. Example 5 shows this behavior.

.content {
	display: flex;
	flex-direction: column;
}

.content .img {
	align-self: center;
}

If all of the elements within <div.content/> need to be aligned the property align-items can be used. Set it to flex-end and they get pushed to the right (except for the image, which is individually centered above). The default left alignment is achieved with the value flex-start.

.content {
	align-items: flex-end;
}

Justify yourself

Another property for alignment is justify-content, which is pretty handy to evenly divide the available space to various elements as seen in example 6. Here we have an image bar and the four images are evenly distributed across the whole width, thanks to the value space-between.

.bar {
	display: flex;
	justify-content: space-between;
}

Another value would be space-around, which also provides for even division, but adds half of the gap width before the element and the other half after. You can test all of the available properties at example 6.

If the images within the image bar have a different size you can use the already mentioned properties align-items and align-self to align them vertically, as seen in example 7. In this case align-items is set to center, so that all images are vertically centered, but the second image is individually aligned to the bottom with the value flex-end. You can test all the available properties at this example. All of them should be self-explanatory except baseline, which is just important for text, so that their baselines line up. In our example it’s the same as flex-end. Note that the second image always remains at the bottom due to its set align-self property.

Pure flexibility

Another strength of Flexbox is its ability to automatically distribute the available space to the elements of the container, which is set to display: flex. If you need three columns with equal width you’d normally have to calculate a little bit and come up with a width of 33.33% for each column. For such purposes Flexbox provides the flex property. To get three equal columns just set flex: 1 for each and that’s it, as illustrated in example 8.

nav, .content, aside {
	flex: 1;
}

If you need the content area to be twice the width of <nav> (and <aside>) set flex: 2 for it and leave the other two at 1.

That’s just the most simple application of the flex property, it’s also possible to set flex-grow, flex-shrink and flex-basis values, but that’s far beyond the scope of this article and pretty hard to digest stuff. I’ve warned you, but if you still want to know about it, head over to the specs.

A bright future

As you can see, Flexbox has great potential to make our lives so much easier if we need to set up a layout for a website. It’s rock solid (at least in the current version) and makes any hacks, collapsing containers or other weird stuff we have to deal with every day, obsolete. Hopefully the current syntax is the final one and every browser will interpret the properties in the same way prospectively.

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • http://www.mattearly.com Matt Early

    The question we have to ask is, is columns and rows the future of web design and development, or is it just the past and present?

  • http://RonBigus.com Ron Bigus

    Looked at all the examples, using chrome…if this is suppose to be the next thing…I’ll wait for the sequel.

    • http://www.css3files.com/ Christian Krammer

      Like I stated in the article, Flexbox is still an experimental feature, but Chrome and Opera already support it to a great extent. Firefox will close up with version 20, which all in all is a pretty good basis then.
      Of course Internet Explorer is behind like always (Flexbox support probably only comes in version 11) and mobile browsers also don’t support it. But it looks like Flexbox is the next big thing regarding to website layouts.
      And like every CSS3 feature it takes time until it’s safe to use it. Did you ever imagine a few years ago that you would ever be able to regularly use border-radius in your CSS, without a prefix, without the fear that any browser couldn’t understand it?

  • Shane Skinner

    Great article, Christian, and very informative. I am loving the flexibility (no pun intended) that Flexbox offers and appreciate your thoroughness in explaining it and some of the properties.