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 containerflex-wrap
controls whether elements will wrap if they exceed the size of the containerjustify-content
tells the container how to distribute the child elements when there is spare space along theflex-direction
axisalign-content
sets the aligment of child elements on theflex-direction
axisalign-items
sets the alignment of child elements perpendicular to theflex-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 theflex-direction
axis (similar toz-index
)flex-grow
determines whether an element can expand to fill free spaceflex-shrink
determines whether an element can shrink to make space for other childrenflex-basis
sets the base size of an element before it grows/shrinksalign-self
allows the child element to override the value set in the parentalign-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:
- Flexbox Froggy, a simple game to help you remember what each property does
- A Complete Guide to Flexbox from CSS-tricks
- The CSS Flexible Box Layout reference from the Mozilla Developer Network