Flexbox is a new layout mode in CSS3 that is designed for the more sophisticated needs of the modern web. This article will describe the newly-stablized Flexbox syntax in technical detail. Browser support is going to grow quickly, so you’ll be ahead of the game when support is wide enough for Flexbox to be practical. Read on if you want to know what it does and how it works!
Authors have long been using tables, floats, inline-blocks, and other CSS properties to lay out their site content. However, none of these tools were designed for the complex webpages and webapps we are making nowadays. Simple things like vertical centering require work. Complex things like flexible grid layouts are so hard that it’s considered ambitious to roll your own, hence the success of CSS grid frameworks. Still, if so many projects needs to do these things, why can’t it just be easy? Flexbox aims to change all that.
The Flexbox specification has been a work in progress for over 3 years. Various browsers have implemented different versions experimentally. In September 2012, the 3rd major revision of the Flexbox syntax reached the W3C Candidate Recommendation stage. This means that the W3C is satisfied with the current syntax and is encouraging browser vendors to implement it.
Flexbox Specification Timeline:
Browsers are adopting Flexbox quickly. Chrome 22+, Opera 12.1+, and Opera Mobile 12.1+ already support Flexbox as described in this article. Firefox 18 and Blackberry 10 will follow soon. I recommend reading this article in a supported browser to see working examples.
Though Flexbox makes it trivial to create layouts that would have been difficult or impossible in the past, it takes some time to get used to the Flexbox way of doing things. New terminology and new abstractions can be a barrier to using Flexbox, so let’s discuss them up-front.
Flexbox consists of Flex Containers and Flex Items. A Flex Container is declared by setting the display property of an element to either
flex the container is a rendered as a block. With
inline-flex the container is rendered inline.
Here is an example declaring a Flex Container.
This article will show all appropriate vendor prefixes in all examples.
Every child of a Flex Container is a Flex Item. There can be any number of Flex Items. Everything outside a Flex Container and inside a Flex Item is rendered as usual. In short, Flexbox defines how Flex Items are laid out inside of Flex Containers.
Flex Items are positioned inside a Flex Container along a Flex Line. By default there is only one Flex Line per Flex Container.
Here is a simple example that shows two items as they are positioned by default: along a horizontal flex line, from left to right.
An important part of customizing your Flexbox is changing the direction of the flex line. By default, the Flex Line goes in the direction of text: left to right, top to bottom.
There is a W3C Working Draft for a new feature called Writing Modes. Writing Modes are a new way to write text right-to-left, or even vertically, as you might in certain languages.
Writing Modes are a work-in-progress, but Chrome currently supports the
direction CSS property. If we set the direction in the previous example to
rtl (right-to-left) then not only is the text drawn right to left, but also the Flex Line changes direction, changing the page layout.
This might clarify why a lot of the Flexbox terminology is so abstract. You can’t just say “right” “left” “up” and “down” when you’re making no assumptions about the language of the page.
To abstract over the writing-mode, Flexbox uses the concepts of the Main Axis and the Cross Axis. Flex Lines follow the Main Axis. The Cross Axis is perpendicular to the Main Axis.
The names for the starting points, ending points, and directions of each axis are as follows:
It is crucial to understand the Main and Cross terminology before continuing. Everything in Flexbox is relative to these axes. In all of our examples the writing-mode will be left-to-right, top-to-bottom, but you must keep in mind that this will not always be the case.
flex-direction allows you to change the axes of the Flex Container. The default value of
row. With this value, Flex Items are laid out in the direction of the
writing-mode. Again, that means left-to-right, top-to-bottom by default. The other values are as follows:
Let’s take our previous example and change the
Now our Flex Items are being laid out vertically.
justify-content property of Flex Containers adjusts the positions of Flex Items on the Main Axis. The possible values are:
Here we set
center to cause Flex Items to be centered on the Main Axis:
center are straightforward.
space-around distribute the whitespace between Flex Items in more subtle ways. This diagram from the specification explains it best:
align-items is complementary to
align-items adjusts the way Flex Items are positioned on the Cross Axis. The possible values are:
Here we set
center to cause Flex Items to be centered on the Cross Axis:
center values are straightforward.
stretch is also fairly simple: it causes Flex Items to be stretched out from the Cross Start to the Cross End.
baseline causes Flex Items to be aligned along their baseline. Baselines are calculated based on the content of the Flex Items. This is best explained by the following image from the Flexbox specification:
Up until now, every Flex Container has had only one Flex Line. Using
flex-wrap you can create Flex Containers with multiple Flex Lines. The possible values for flex-wrap are:
flex-wrap is set to
wrap, Flex Items wrap onto additional Flex Lines if there is not enough room for them on one Flex Line. Additional Flex Lines are added in the direction of the Cross Axis.
Here is an example using
wrap-reverse is the same as wrap except new Flex Lines will be added in the opposite direction on the Cross Axis.
align-content modifies the behavior of
flex-wrap. It is similar to
align-items, but instead of aligning Flex Items, it aligns Flex Lines. As you might expect, its possible values are similar:
These values are analagous to their counterparts in
In this example we set
flex-flow is a shorthand for
flex-flow: [flex-direction] [flex-wrap]
A Flex Item is any direct child of a Flex Container. Text in a Flex Container also gets treated as a Flex Item.
The contents of Flex Items render as normal. For example, while setting float on a Flex Item does nothing, you could have a floated element inside of a Flex Item.
Flex Items are said to have a Main Size and a Cross Size. The Main Size is the size of the Flex Item in the dimention of the Main Axis. The Cross Size is the size of the Flex Item in the dimention of the Cross Axis. Effectively, the width or height of a Flex Item may be its Main Size or Cross Size depending on the Flex Container’s axes.
The following properties adjust the behavior of Flex Items.
order is the simplest one. Setting orders for Flex Items adjusts their order when rendered. In this example, we set the
order of one Flex Item to -1, causing it to be displayed before any other Flex Items.
This can be useful for accessibility, where the document order and the displayed order may need to be different.
You may be familiar with the normal effect of
margin: auto;. In Flexbox it does the same sort of thing, but it’s even more powerful. An “auto” margin will absorb extra space. It can be used to push Flex Items into different positions.
Here we declare
margin-right: auto; on the first Flex Item, causing all the extra space to be absorbed to the right of that element:
Here we use
margin: auto; to achieve the holy grail of CSS layout: true vertical centering:
align-self property of Flex Items effectively overrides the Flex Container’s
align-items property for that item. It has the same possible values as
In this example we give different
align-self values to each Flex Item:
I included two baseline Flex Items because their alignment is only relative to one another.
Now we’re finally going to put the flex in Flexbox.
flex specifies how a Flex Item will be prioritized when free space is being distributed on the Main Axis.
Let’s look at each of the common values one at a time.
This syntax specifies a number that represents the ratio of free space that should be taken by this Flex Item.
In this example, the first Flex Item consumes 2/4 of the free space, and the other two Flex Items consume 1/4 of the free space each:
It can be useful to set the number to 1 for every Flex Item, causing free space to be distributed evenly:
A Flex Item with its
flex value set to
initial will be inflexible when there is free space, but can shrink smaller if needed.
A Flex Item with its
flex value set to
auto will be fully flexible along the Main Axis.
auto currently works in Opera 12.11 but does not work in Chrome 23.0.1271.95. You can often work around this by using
A Flex Item with its
flex value set to
none will be fully inflexible in all situations.
flex can also be used as a shorthand for specifying
flex-basis in one declaration:
flex: [flex-grow] [flex-shrink] [flex-basis]
Most use-cases do not require this syntax. Further, it requires a more specialized understanding of the flex algorithm. If you’re feeling brave, take a look at the specification.
You can also specify each of
flex-basis as separate properties. I strongly recommend against this: when using the
flex shorthand, more sensible defaults are applied to the values that are not given.
When it is implemented,
visibility: collapse; will be distinct from
visibility: hidden; and
display: none; for Flex Items. With
collapse, the element will affect the Cross Size of the Flex Container, but it will not be displayed nor will it consume any space on the Main Axis. This will be useful for dynamically adding and removing Flex Items without affecting the Flex Container’s Cross Size.
visibility: collapse; does not appear to be correctly implemented in any browser.
visibility: collapse; appears to do the same thing as
visibility: hidden; in current implementations. I expect this to change soon.
You can see a good mocked-up example of how
collapse will work in the spec.
As you can see, Flexbox is a powerful new layout mode that will revolutionize layout for websites. As you can also see, it requires a whole new way of thinking. Hopefully this article has prepared you to start making websites with Flexbox. I don’t know about you, but it seems to me that the future is awesome.