So flexbox, much wow!

Flexbox is amazing. Today I learned that it is a thing, and it straight up exploded my brain with its awesomeness. Let’s talk about how awesome it is, so that your brain may get exploded too!

What is flexbox?

Flexbox (short for “flexible box”, shockingly) is a relatively new layout mode in CSS3. It can be used by declaring display: flex; on the container, i.e. on the parent element of the content you want to lay out (for some browsers, e.g. Safari, you’ll need to use -webkit-flex;).

Why is it awesome?

It allows you much more intuitive control over the layout of boxes on the page than other, older layout modes such as block, inline, etc., even when you don’t know the size of the relevant elements on the page.

To my mind, its main advantages (read: brain-exploders) are:

Vertical alignment is completely painless

Trying to vertically center an element in CSS has always made me want to cry. It always seemed to involve many too many layers of superfluous wrapper <div>s, and the rock-vs-hard-place alternatives of either using weird and wholly unintuitive hacks involving relative positioning and transform: translateY, or resorting to layouts such as inline or table which allow you to use the vertical-align property. In short, it was not fun.

Enter flexbox! With flexbox’s align-items, vertical alignment is a one-line affair, and holds no mystery. And there’s also justify-content for horizontal aligment.

Check it out:

HTML:
<div id="parent">
    <div>I'm so centered!</div>
</div>
CSS:
#parent {
  display: flex;
  align-items: center;
  justify-content:center;
}
Result:
I'm so centered!

I don’t know about you, but for me this vertical alignment thing is a HUGE. DEAL. But the flexbox amazement doesn’t stop there…

Switching between rows and columns is a snap

Imagine you have some arbitrary content that looks something like the following:

HTML:
<div id="parent">
    <div>A</div>
    <div>B</div>
    <div>C</div>
    <div>D</div>
    <div>E</div>
    <div>F</div>
    <div>G</div>
    <div>H</div>
    <div>I</div>
    <div>J</div>
    <div>K</div>
    <div>L</div>
</div>
Result:
A
B
C
D
E
F
G
H
I
J
K
L

How bored are you looking at that boring list of items? So bored!

To break things up in a more interesting and pleasing way, you might decide you want to display your items in rows. You could do this by adding wrapper divs, but that would mean hard-coding the row breaks between elements. You could also use floats, but then you have to deal with clearfixes and all kinds of other weird unexpected stuff that happens when you use float for laying things out.

Or, you could use flexbox! Flexbox has two useful properties for automatically laying out an unstructured sequence of elements into rows or columns: flex-direction and flex-wrap.

By setting flex-direction to row (default) or column, you can easily control whether the elements will be laid out left-to-right (as if you were floating them to the left) or top-to-bottom (as if you weren’t styling them at all, like in the baseline example above). Then, by setting flex-wrap to wrap (instead of the default nowrap), you can tell flexbox to wrap the items that don’t fit in the parent’s width (or height if you’re using columns) onto the next line. (Note that you need to set some kind of width/height on the parent, or else flexbox won’t know when to start the next line.)

For convenience, you can use the property flex-flow to simultaneously declare the flex-direction and flex-wrap, as in flex-flow: column wrap;.

Going back to that same HTML from earlier, let’s see how it looks if we now use flexbox to create wrapped rows:

CSS:
#parent {
  width: 40%;
  display: flex;
  flex-flow: row wrap;
  align-items:center;
  align-content:space-between;
}
Result:
A
B
C
D
E
F
G
H
I
J
K
L

ZOMG how beautiful, thanks flexbox!

Looking at the CSS, you’ll recognize align-items from earlier, but what’s the deal with align-content? Well, while the align-items property controls vertical alignment within a given line of items, the align-content property controls the vertical alignment of the lines themselves. This only applies when you have more than one line; if your items only take up one line, align-content has no effect. Your options for align-content still include center, flex-start, and flex-end, but also space-between and space-around, which try to maximize - you guessed it - the space between lines or the space around each line. Check out the resources at the end of this post for more examples of how align-content works.

Getting back to our example, let’s say that now you’ve decided that columns would make a lot more sense than rows. Thanks to flexbox, this is a breeze! We can just set the parent’s height and change row wrap to column wrap. Voilà:

CSS:
#parent {
  height: 150px;
  display: flex;
  flex-flow: column wrap;
  align-items:center;
  align-content:space-between;
}
Result:
A
B
C
D
E
F
G
H
I
J
K
L

Note that while 4 items previously fit on a line, only 3 items fit in a column. Flexbox don’t mind! It simply wraps when it hits the parent’s height, happy as a clam.

Note that when we use column, we basically switch the horizontal and vertical axes, as far as flexbox is concerned. This means that instead of controlling vertical alignment, align-items and align-content now control horizontal alignment; similarly, justify-content, which as mentioned earlier initially controls horizontal alignment, controls vertical alignment when we’re using column.

Think I’m done raving about how awesome flex-flow is? Think again! Behold another magical feature of flex-flow

Re-ordering items is easy as 1-2-3

So, you have elements that you want to display in a different order than they appear in the HTML document? Well, before flexbox, you’d probably resort to using JavaScript; for a CSS-only approach you’d be looking at even more weird hacks. None of these are ideal.

Flexbox to the rescue!

Looking back at the example from the last section, what if you decide that although these elements are arranged alphabetically in the HTML, you want to display them in the reverse order?

No big deal, flexbox has your back. In addition to row and column, flex-direction also has the options row-reverse and column-reverse. Can you guess what they do?

CSS:
#parent {
  width: 40%;
  display: flex;
  flex-flow: row-reverse wrap;
  align-items:center;
  align-content:space-between;
}
Result:
A
B
C
D
E
F
G
H
I
J
K
L

Now the items have been laid out right-to-left instead of left-to-right. But the rows themselves are still laid out in the default top-to-bottom order; do you think flexbox might have an easy way to switch that around too?

OF COURSE IT DOES. All you have to do is change the flex-wrap. Behold wrap-reverse:

CSS:
#parent {
  width: 40%;
  display: flex;
  flex-flow: row-reverse wrap-reverse;
  align-items:center;
  align-content:space-between;
}
Result:
A
B
C
D
E
F
G
H
I
J
K
L

Pretty intuitive, eh? By combining row-reverse and wrap-reverse, we’ve displayed the items right-to-left and bottom-to-top, making it look like they were in reverse-alphabetical order all along.

If you need finer-grained control, setting the order property on the child elements allows you to re-order them as you see fit. The default value of order is 0, so by changing a child’s order to a higher or lower number (negatives are OK), you can affect its positioning relative to the other elements: the elements will be rearranged from lowest to highest order value. For example:

HTML:
<div id="parent">
    <div id="A">A</div>
    <div id="B">B</div>
    <div id="C">C</div>
    <div id="D">D</div>
</div>
CSS:
#parent {
  display: flex;
  flex-flow: column;
}

#B { order: 1; }
#D { order: -1; }
Result:
A
B
C
D

Convinced? Learn more!

Oh, what’s that? Your brain has exploded and you can’t wait to get started with flexbox? Well, check out this adorable frog tutorial - it’s so fun, you won’t even realize you’re learning flexbox basics!

For a more in-depth (and significantly less cute) explanation of flexbox features, try this CSS-Tricks article.

Is there a catch?

OK, OK, I’ve ranted enough about the glories of flexbox. Surely it has a dark side?

Well, technically the flexbox layout isn’t a fully-fledged part of the CSS standard yet (it’s in the “Last Call Working Draft” stage of the pipeline), which means it’s possible it will change slightly before being accepted as an official recommendation that all browsers should support.

This essentially means that browser support exists, but isn’t perfect. (Why, IE, whyyyy?) According to MDN, the flexbox layout “is an experimental API that should not be used in production code.”

So if you use flexbox, be prepared to resort to some of those weird hacks in cases where it’s not supported. But look on the bright side: going back to the old, clunky ways once in a while will just make you more appreciative of the fact that we live in the beautiful, dawning age of flexbox! And don’t forget keep an eye on the flexbox specification as it becomes a more established part of the CSS standard.


Sources: