So flexbox, much wow!
01 Dec 2015Flexbox 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:
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:
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 div
s, but that would mean hard-coding the row breaks between elements. You could also use float
s, 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 float
ing 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:
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à:
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?
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
:
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:
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:
- Flexbox Froggy (thanks RC facilitator Allie for the recommendation!)
- A Complete Guide to Flexbox and The CSS Standards Process on CSS-Tricks
- Using CSS flexible boxes and Layout Mode on MDN
- CSS3 flexbox examples by Helen Emerson
- Changing element display order in css (without flexbox) by Pam Griffith
- Some hack-tastic StackOverflow questions
- The W3C flexbox specification