Flexbox

I've been using flexbox for over a year for layout in CSS. Unlike its sibling CSS Grid, flexbox has had widespread browser support for a long time. This is a short summary of what flexbox does, and some uses for it in practice.

What is Flexbox?

Flexbox is a layout system which allows you to abstract away a lot of the specifics of laying out items in a grid. It caters to use-cases which have historically been clunky to implement, including creating complex rows and columns, laying out flexible elements, adapting to bidirectionality, and overriding source ordering.

The best at-a-glance resource I've found for flexbox is the brilliant visual CSS-Tricks guide. Rather than repeat the comprehensive documentation already available elsewhere, here's a brief summary.

Flexbox layouts are composed of two types of elements—a parent flex container, and a number of children. Creating a flex container is as simple as setting display: flex; (or display: inline-flex;) on it. When you set display: flex; on a flex container element, these are the default properties it receives:

display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: flex-start;
align-content: flex-start;
align-items: flex-start;
  • flex-direction sets the overall flow of the elements in the container
  • flex-wrap controls whether elements will wrap if they exceed the size of the container
  • justify-content tells the container how to distribute the child elements when there is spare space along the flex-direction axis
  • align-content sets the aligment of child elements on the flex-direction axis
  • align-items sets the alignment of child elements perpendicular to the flex-direction axis

You can also set flex-direction and flex-wrap using the shorthand:

flex-flow: <'flex-direction'> || <'flex-wrap'>;

The child elements will have these default properties:

order: 0;
flex-grow: 0;
flex-shrink: 1;
flex-basis: auto;
align-self: flex-start; 
  • order determines which elements have predecence along the flex-direction axis (similar to z-index)
  • flex-grow determines whether an element can expand to fill free space
  • flex-shrink determines whether an element can shrink to make space for other children
  • flex-basis sets the base size of an element before it grows/shrinks
  • align-self allows the child element to override the value set in the parent align-items for a specific element

You can also set flex-grow, flex-shrink, and flex-basis using the shorthand:

flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]

The great thing about both the parent and child properties is that they are all relative to the flex-direction set on the parent element. This makes it incredibly easy to influence the layout without needing to change other styling. flex-direction is also determined based on the dir attribute, making it even more adaptive.

Use cases

Holy grail

The classic three-column 'holy grail' layout with a sticky footer. This uses flex-direction: column; on the wrapper to create the base layout with flex-grow: 1; set on the content area to expand it to fill the page window, and a standard column layout in the content area with column precedence set using order.

Bidirectional

A simple bidirectional grid layout which reflows based on the directionality of the <body> element. Since other properties are already set relative to the flex-direction, this is incredibly powerful when used for more complex layouts.

Trello

A basic Trello-like layout of cards in columns. This uses a column layout inside a grid of tall rows to create a card structure. See the Bugs section below for a limitation of this pattern.

Flexible grid

A simple flexible grid of small and large items, constructed using flex-basis and flex-grow to control the relative sizing of elements. This also features a work-around to prevent rows or orphaned elements expanding to take up the whole row, by placing a zero-height element with a large flex-grow value at the end of the content.

Bugs

When creating the Trello example I found a bug in the browser implementation of flex-direction: column; which appears to be widespread (see the Chromium bug report and a related Stack Overflow post). The issue comes from the browser's calculation of the width of the flex container—after the first row, the container fails to expand to encapsulate the remaining rows (presumably because container width calculation is traditionally horizontally- rather than vertically-driven). This can be avoided if you can give your column a defined width, but the specific case of having an expanding column layout doesn't yet seem to be supported.

Flexbox resources

A few resources I've found helpful when learning and using flexbox: