Learn You a Flexbox for Great Good!

This article is outdated and no longer accurate. Find up-to-date information about flexbox at HTML5 Please.

Yet Another Note (2012-05-13): It might be obvious that the flexbox spec is changing often, but a kind commenter suggested I add a note here regarding the fact that in the spec, the flex() function has been replaced by the `flex` property, which makes plenty of stuff in this article obsolete. Also, expect more to change. I will most likely leave this article as is. I will write an update as soon as I see an implementation in at least one more browser. As of this note’s date, Chrome still supports the version described below. —Stephen

Note (2012-05-12): I have added -moz-, -ms- and -o- vendor prefixes to all code examples and the demo. Here’s why. The spec is—at the time of this note—still in flux, so I intentionally left out the non-prefixed properties/values.

So you want to learn Flexbox? Perhaps you’ve heard about it. Perhaps you’ve read a tutorial or two about it. Perhaps you’ve even played around with it already.

If you’ve never heard of Flexbox, or if it’s been awhile since you’ve used it, forget what you know. We’re starting over! The spec has been rewritten; the last version at the time of this writing is dated 29 November 2011!

What you’ll need

CurrentlyAt the time of this writing, Chrome Canary Google Chrome has a partial implementation of the spec. If you’d like to follow along, you’ll need nothing more than Chrome Canary Google Chrome and your favorite text editor.

Ready? Let’s get to it!

What is Flexbox?

Flexbox is a nickname for CSS Flexible Box Layout Module. It’s one of a few CSS Working Drafts having to do with visual layout. Flexbox offers us a new box model which has been optimized for laying out user interfaces. In short: the children of a “box” can be ordered either vertically or horizontally within their parent, and we can control what happens to any remaining space. It is possible to nest these boxes, allowing for very complex layouts.

Caution!

There are other CSS layout modules in development which, in my opinion, are much more suited to general page layout than Flexbox. Flexbox is fairly straightforward, but can become unruly when used for complex layouts. In any case it is not the best solution for all types of layout. But for UI-components like buttons, forms, toolbars or rows and columns of content/media blocks for which you’d normally use floats, Flexbox makes code simpler and is a huge time-saver. Flexbox is designed to play nicely with existing CSS properties. Thus, you are still free to use floats or other types of positioning on non-Flexbox elements.

Three Little Boxes

If you’re feeling a bit lazy, you’re welcome to simply download and edit the demo page Otherwise…

Open your editor, create a simple HTML document with a single box. In this case, we’ll use a div:


    <!DOCTYPE html>
    <html lang="en">
        <head>
             <meta charset="utf-8">
             <title>Flexbox</title>
        </head>
        <body>
            <div>
            </div>
        </body>
    </html>

Great, But it would be nice to see something, so we’ll have to add some style:


    <style>
        body>div {
            height: 500px;
            padding: 1em;
            background-color: gray;
        }
    </style>

Now we’ll put three boxes into our div. These are, of course, the first div‘s children:


    <div>
        <div>A</div>
        <div>B</div>
        <div>C</div>
    </div>

Let’s style those as well:


    div>div {
        width: 100px;
        height: 100px;
        background-color: pink;
    }

Now look at this page in Canarythe browser. Nothing unusual here, just three block-level elements one under another, as block-level elements are known to do. But we’ll put a stop to that. We’ve created our own Flexbox playground, so let’s play.

Defining a flexbox

We would like to apply the magic of Flexbox to the children of our parent div. We do so with the display property. By applying display: flexbox; to our parent div, we tell it to use the Flexbox box model. If we wanted our parent div to be inline instead of block-level, we’d use display: inline-flexbox;.


    body>div {
        display: -webkit-flexbox; /* We need the prefixes for now, unfortunately. */
        display: -moz-flexbox;
        display: -ms-flexbox;
        display: -o-flexbox;
        height: 500px;
        padding: 1em;
        background-color: gray;
    }

Our three child divs, which we’ll call flexbox items from now on, now live according to the Flexbox box model. Beware: there are rules that determine what a flexbox item is. For example, if we were to use position: absolute; on one of the three boxes, it would no longer be a flexbox item since we’ve applied a different positioning model. Read more about flexbox items in the spec.

Back to our little exercise. Take a look at the page in your browser. The flexbox items look a bit as if we had applied inline, inline-block or float to them. This is because the Flexbox default is to position flexbox items horizontally. The main difference so far is that we have only added a rule to the parent and not to the items themselves.

Source-order independence

Flexible Box Layout Module gets its name from the fact that it allows us to create flexible boxes. In other words, boxes can become flexible by utilizing available space. We’ll get to that in a minute. But Flexbox offers something at least equally important to us, especially in this Age of Mobile: source-order independence. Let’s play around and see how we can change the order of flexbox items.


    body>div {
        display: -webkit-flexbox;
        display: -moz-flexbox;
        display: -ms-flexbox;
        display: -o-flexbox; 
        -webkit-flex-flow: row-reverse;
        -moz-flex-flow: row-reverse;
        -ms-flex-flow: row-reverse;
        -o-flex-flow: row-reverse;
        height: 500px;
        padding: 1em;
        background-color: gray;
    }

OMG. Our flexbox items are now right-aligned and the order is reversed! We do this with the flex-flow property, for which row is the default value. row-reverse flips this around. You might have already guessed that when you want to position flexbox items vertically, you would use column or column-reverse. At the time of this writing, CanaryChrome does not support column-reverse, but try out column and see what happens! When you’re done playing around, set the value back to row and we’re ready for our next step.

By the way, flex-flow also takes a value for wrapping flexbox items to new rows (or columns, depending on which you’re using). The values wrap and wrap-reverse serve this purpose, as the default is a single row (or column) of flexbox items which overflows the parent. wrap and wrap-reverse still haven’t been implemented at the time of this writing (I’m saying that a lot). But let’s say, just for fun, that we could use wrap today:


    body>div {
        display: -webkit-flexbox; 
        display: -moz-flexbox;
        display: -ms-flexbox;
        display: -o-flexbox;
        -webkit-flex-flow: row wrap; /* `wrap` gives us a multi-line flexbox. */
        -moz-flex-flow: row wrap;
        -ms-flex-flow: row wrap;
        -o-flex-flow: row wrap;
        height: 500px;
        padding: 1em;
        background-color: gray;
    }

Mirror, mirror…

All the properties dealing with order, direction or alignment of flexbox items are influenced by the current writing mode. The writing mode is the original direction of the text. Many of us are used to top-to-bottom, left-to-right. But as soon as these are changed, the output of the directional Flexbox properties will also change. You’ve already seen what row-reverse does. But what if your writing mode isn’t the default (top-to-bottom, left-to-right) but top-to-bottom, right-to-left? Your flexbox items would be laid out from right-to-left in the first place, and row-reverse would flip things so they’re left-to-right.

Try it out:


    body>div {
        display: -webkit-flexbox; 
        display: -moz-flexbox;
        display: -ms-flexbox;
        display: -o-flexbox;
        direction: rtl; /* The `writing-mode` property currently has no visual effect in Chrome. The `direction` property will suffice for our example. */
        -webkit-flex-flow: row;
        -moz-flex-flow: row;
        -ms-flex-flow: row;
        -o-flex-flow: row;
        height: 500px;
        padding: 1em;
        background-color: gray;
    }

Look at the page in your browser. Now replace row with row-reverse. See what happens?

Confusing? Perhaps a little at first, but the properties all work logically based on the current writing mode. As most of us usually work with the same writing mode most of the time, it shouldn’t be much of a problem.

In order to understand the effect many Flexbox properties have on flexbox items, it is important to understand what the main axis and the cross axis are. The main axis is the axis along which the flexbox items are placed. In other words, if the flexbox items have been placed horizontally (flex-flow: row;), then the main axis is horizontal. The cross axis is perpendicular to the main axis. In our example, that would be vertical. When using flex-flow: column;, this is switched: the main axis is vertical and the cross axis is horizontal.

That’s a pain to explain well. Just to be sure we’re clear, here’s an illustration:

When items are horizontally positioned, the main axis is horizontal.

Remember main axis and cross axis, because we’ll need them in a bit.

Order! Order in the court!

Let’s look at another property which helps the cause for source-order independence: flex-order.

In your example code, make sure you’ve set flex-flow to row and have removed direction: rtl;. If things are as they should be, you’ll have three flexbox items: A, B and C, in the top left of body>div. Imagine that although our code contains these items in that order, that we want to display them in the order A-C-B. To do this, we’ll use flex-order:


    div:nth-child(2) { /* Yes, I could have used an ID or a class. But, hey, whatever. */
        -webkit-flex-order: 1;
        -moz-flex-order: 1;
        -ms-flex-order: 1;
        -o-flex-order: 1;
    }

Check things out in your browser. The order of the flexbox items should be A-C-B.

flex-order places flexbox items into ordered groups. Boxes without an explicit flex-order are in group 0 and remain in source order. In our example, the second flexbox item (B) is placed in group 1. A and C remain in group 0 and in source order (A before C). Since group 1 comes after group 0, the B comes last. If we had wanted the order B-A-C, we could have left B in group 0 and put A and C into group 1:


    div>div:first-child,
    div>div:last-child {
        -webkit-flex-order: 1;
        -moz-flex-order: 1;
        -ms-flex-order: 1;
        -o-flex-order: 1;
    }

Flexibility

One of the nicest aspects of Flexbox is the ability to create flexible elements. We can decide what to do with any remaining space in our body>div (in this example). We can divide this space up between the flexbox items, or we can make the widths or heights of one or more of these items flexible, alotting a certain amount of available space to each.

We’ll look at flexibility first and then come back to distributing available space.

Imagine that our three flexbox items are buttons in a web application which might also be used on mobile devices. Sometimes we have three, but sometimes we only have two (just nod and go along with it). We’d like to say, “No matter how many of these buttons there are, I want them all to generally be the same width, and these widths should be such that the row of buttons takes up all the available width of the parent.” We’d normally resort to JavaScript for these types of layout problems, but Flexbox might put an end to that. See what happens when we make our flexbox items flexible with the flex() function:


    div>div {
        /* width: 100px; */
        width: -webkit-flex(1 0 100px);
        width: -moz-flex(1 0 100px);
        width: -ms-flex(1 0 100px);
        width: -o-flex(1 0 100px);
        height: 100px;
        background-color: pink;
    }

The flex() function can be used as a value for width or height. flex() takes three values: positive flex, negative flex and preferred size. The last two parameters are optional; the default for negative flex is 0 and the default for preferred size is 0px. Here’s how flex() works in a nutshell:

  1. The preferred width is applied to the flexbox items.
  2. If there is any space left over in the parent, this space is divided up into parts and added to the widths of the flexbox items according to the positive flex value.
  3. If the flexbox items overflow the parent (e.g. together they are wider than the parent), then the negative flex value is used for determining the widths of the items. Please note that negative flex is a positive value (e.g. 2 and not -2).

A positive flex value of 1 basically means “one equal part of the available space”. A value of two would mean something like “twice the amount of available space as the items that have flex(1)”. So it’s nothing like “two parts whiskey, one part cola”. The easiest way to learn it is to try it out. Type the following code under your rules for div>div:


    div>div:first-child,
    div>div:last-child {
        width: -webkit-flex(2);
        width: -moz-flex(2);
        width: -ms-flex(2);
        width: -o-flex(2);
        background-color: magenta; /* This allows us to see the difference clearly. Plus, it hurts your eyes. */
    }

If you check your browser, you’ll see that the first and the last flexbox items don’t each have 2 parts of the available space. Rather, they have two times as much available space as the middle box, which has flex(1). I know, I know. Just be glad you’re not a browser maker. Unless you are, in which case: have fun and please get this implemented ASAP!

Also, please note that this does not mean that the two outermost boxes are two times as wide as the center box. We’re only dealing with how the available space in the parent is being distributed.

Remove the declaration you just added. Remove one of the divs and look at the result in your browser. Once you’ve seen what happens, put the div back in again.

There’s plenty more about flex() and any other gory details you might want to know about Flexbox; these can all be found in the spec.

Alignment of flexbox items

Did you remember everything about main axis and cross axis? Excellent. Because the flex-pack property determines how flexbox items are aligned along the main axis. In our example file, the main axis is horizontal. In order to study the effect of flex-pack, remove flex() and change the width back to 100px:


    div>div {
        width: 100px;
        height: 100px;
        background-color: pink;
    }

flex-pack accepts one of four possible values: start, end, justify and center. Pretty clear. Let’s center our flexbox items. We do this on the parent:


    body>div {
        display: -webkit-flexbox;
        display: -moz-flexbox;
        display: -ms-flexbox;
        display: -o-flexbox;
        -webkit-flex-flow: row;
        -moz-flex-flow: row;
        -ms-flex-flow: row;
        -o-flex-flow: row;
        -webkit-flex-pack: center; /* <-- */
        -moz-flex-pack: center;
        -ms-flex-pack: center;
        -o-flex-pack: center;
        height: 500px;
        padding: 1em;
        background-color: gray;
    }

Go ahead and play with the other values until you like it.

Of course, there is a property for aligning flexbox items along the cross axis: flex-align. The possible values differ slightly from flex-pack. The most important thing to remember is that while flex-pack is applied to the parent of the flexbox items, flex-align is applied to the flexbox items themselves.


    div>div {
        width: 100px;
        height: 100px;
        background-color: pink;
        -webkit-flex-align: center; /* Also: start | end | baseline | stretch  <-- Try these vales as well! */
        -moz-flex-align: center;
        -ms-flex-align: center;
        -o-flex-align: center;
    }

Not all the values are supported yet, but I don’t think we’ll need to wait very long. As the spec solidifies, implementation should come fairly quickly. The browser makers are quite interested in Flexbox.

Enough! Time to play

There are a couple of other properties having to do with multi-line flexboxes, but since we can’t try those out yet, we’ll stop here for now. Hopefully we’ve handled enough material to get you started playing around with the “new” Flexbox. Try and consider practical applications. How could Flexbox help within the context of “responsive design” and mobile? What possibilities open up for form styling? Navigation?

You don’t need to be able to use this today in actual projects to learn and experiment with the possibilities. Implementation might come quicker than you think, and you’ll already have a head start.

Have fun!

Note: This article first appeared in the Dutch language for the Fronteers Advent Calendar. Payment for the article was a modest donation to ICCF Holland.

Coping with CSS vendor prefixes

Peter-Paul Koch drops a PPK-bomb on CSS vendor prefixes, the latest post in what seems to be a series of rants which get everyone thinking and talking: not necessarily agreeing. But if you know PPK, then you know that’s probably not the point.

You should read the post. Then form an opinion. Mine is that vendor prefixes are no fun and quite annoying, but a necessary evil. At least for now. There’s no need for me to go into why, as Jonathan Snook makes the point well.

My biggest problem with vendor prefixes is the repetition (read: not the amount of typing), and the fact that I’ll one day need (okay, want) to go back and clean prefixed rules up once they’re no longer necessary or when the implementations change, which they can. I just want a clean style sheet.

A few workarounds, or deal-withs, were mentioned in the comments of the aforementioned posts:

  1. A single “beta” prefix
  2. CSS preprocessors
  3. A separate style sheet

I like the last option the most, hat tip to Bridget Stewart for beating me to it. A separate style sheet fits my current practice of giving each element of design language its own file (I know about the performance implications, but there are plenty of solutions to that). So a generic group of style sheets for a given website might look like this:

  • layout.css
  • type.css
  • color-img.css
  • vendor.css
  • ie[x].css

This is clean. Non-prefixed properties are entered into the normal style sheets, and will (hopefully) be ignored by browsers which don’t understand them. Prefixed properties are placed in vendor.css. And what I would really love is for CSS3, Please! to generate vendor.css for me (That was a hint, guys). Sure, there’s the risk of the spec changing, so it’s up to the designer/developer to be wise in deciding which things should be specified without prefix in the normal style sheets.

Why not the other two?

To be honest, something like -beta- might not be a bad idea, but as of yet, the fact that vendor prefixes are browser-specific is the only useful thing about them. A universal prefix is just that, universal, which could potentially introduce the same problems we would have with no prefixes at all.

I’m not a big fan of CSS preprocessors, or at least I haven’t seen one I’ve liked. We’re talking about CSS; it’s not all that hard to deal with. My problem is not with typing things out three or four times. And I don’t need a preprocessor to do that for me, as prefixes and things like rgba fallbacks are easily accomplished in any decent editor through snippets or scripting. And for those without a decent editor, just use something like CSS3, Please!.

How do you cope?

You only need to subscribe to www-style for about a week before realizing it’s going to take more than three people calling “-beta- prefix!” to get browsers to do it. When you dig down deep enough, there are some very, very smart people who have thought a lot about certain things (and admittedly less about others). It would be a good practice to research or ask why something is as it is, and perhaps participating in www-style and submitting ideas.

You could also try vendor.css. If you hate prefixes, at least you’ve gathered them all together in their own little prefix hell.

How do you deal with vendor prefixes?

A gentle introduction to CSS3 Flexible Box Module (Part 1)

This article is outdated and no longer accurate. Find up-to-date information about flexbox at HTML5 Please.

Note: There is no Part 2 to this introduction, as the Flexbox spec has been changed significantly since this post was written. I did, however, write up an introduction to the newer version of the spec, though I couldn’t really call it Part 2.

A portion of what we do as web designers involves arranging elements horizontally or vertically on the screen. As of yet, CSS lacks a suitable mechanism for this task. Enter CSS3 Flexible Box Module (“Flexbox” for short).

Flexbox is one of three W3C draft specs (as of this writing) dealing with general layout issues and has its strengths and weaknesses compared to the other two. But as it has already been implemented in Firefox (and I predict there is a good chance it will be implemented in Safari in some form), you might want to play around with it. Even if it doesn’t get implemented in anything other than Firefox, some of the principles regarding flexible available space have already been injected into the other modules. Plus, it’s pretty fun.

The draft describes Flexbox as:

[...] a CSS box model optimized for interface design. It provides an additional layout system alongside the ones already in CSS. [CSS21] In this new box model, the children of a box are laid out either horizontally or vertically, and unused space can be assigned to a particular child or distributed among the children by assignment of “flex” to the children that should expand. Nesting of these boxes (horizontal inside vertical, or vertical inside horizontal) can be used to build layouts in two dimensions. This model is based on the box model in the XUL user-interface language used for the user interface of many Mozilla-based applications (such as Firefox).

This is pretty clear. It implies two important things:

  1. No more abusing floats, and no more getting abused by floats
  2. We can create true flexible layouts, and the browser will do the calculations for us

Basically, Flexbox is a small part of XUL ported to CSS. Cool as it may be, I remain of the opinion that the power of Flexbox is in the layout of things like UI components (think forms and toolbars and such) rather than in general page layout. So let’s not get carried away and make Flexbox the new float. For general page layout, we need a true grid-based model; I’ll come back to that in the near future. For now, let’s dive in.

Flexbox gives us a new value for the display property (the box value), and eight new properties:

  • box-orient
  • box-flex
  • box-align
  • box-direction
  • box-flex-group
  • box-lines
  • box-ordinal-group
  • box-pack

Today, we’ll ease into this and just focus on box-orient and box-flex, and tackle the other properties in Part 2.

Let’s say we have three paragraphs, each of which introduces one of three product lines for a client website. Our designer has determined that these teaser paragraphs are to be placed adjacent to one another along a horizontal axis, essentially forming three columns.


<div id="products">
    <p id="phones">First child</p>
    <p id="computers">Second child</p>
    <p id="fast-cars">Third child</p>
</div>

How would you currently tackle this? Most, without thinking, would simply float these paragraphs, perhaps adding overflow:hidden; to the parent in order to clear the floats. Nothing very special. But we could also do it quite easily with Flexbox:


#products { 
    display: box;
    box-orient: horizontal;
    }

In the above code, we’re simply telling the parent to behave according to this (flex)box model, and to lay out all its children along the horizontal axis. No floats. Yay.

box-orient accepts four values, but two of them are important for all intents and purposes: horizontal and vertical. Self-explanatory.

The widths of the children remain as specified (or their inherent width if not specified). This means that if the total widths of all the children is less than the total width of the parent, we’ll get something like this:

3 child elements retain their inherent widths within the parent element

But what if you wanted paragraphs one and two to have specific widths and paragraph three to adjust itself depending on the available space within the parent? Flexbox to the rescue:


#products { 
    display: box;
    box-orient: horizontal;
    }
    #fast-cars {
        box-flex: 1;
        }

Here, we’re telling the last child to become flexible, and to take up available space. Since we’ve only allocated space to one element, it will take up all of the available space:

The 3rd child element, having flex, takes up the available space.

Note that the element only becomes flexible along the orientation axis of the box; in this case the element becomes flexible horizontally.

The value for box-flex is relative. So if we were to make the second and third children flexible:


#products { 
    display: box;
    box-orient: horizontal;
    }
    #computers {
        box-flex: 1;
        }
    #fast-cars {
        box-flex: 1;
        }

These would each take up the same amount of available space, in fact dividing the available space equally between them.

2 of the 3 child elements share the available space in the parent element.

Should we give the last child box-flex: 3;, then it would take three times as much available space as the second child.

Check out the demo (this will only work in Firefox) or download the demo source code (.zip-file, 1kB).

Without even considering the other six properties, there are lots of possibilities here. Although I am not in favor of using this module for page layout, it can be done, as you can see in the demo.

We’ll get back to the other properties at a later date. In the meantime, if you want to play around with this, why not? It will only work in Firefox work in Firefox and (newer) webkit browsers; just prefix the display value and properties with -moz- or -webkit- respectively:

  • display: -moz-box;
  • -moz-box-orient
  • -moz-box-flex
  • display: -webkit-box;
  • -webkit-box-orient
  • -webkit-box-flex

Please be advised: this is meant to be a surface-level introduction to a draft spec. At the time of this writing, most people won’t find this applicable to anything outside of experimentation. There is, however, value in learning about the content of somewhat lesser-known working drafts, if only to be able to compare one to another.

Enjoy!

Creative Commons License
A Gentle Introduction to CSS3 Flexible Box Module (Part 1) by Stephen Hay is licensed under a Creative Commons Attribution 3.0 Unported License.