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-directionsets the overall flow of the elements in the container
flex-wrapcontrols whether elements will wrap if they exceed the size of the container
justify-contenttells the container how to distribute the child elements when there is spare space along the
align-contentsets the aligment of child elements on the
align-itemssets the alignment of child elements perpendicular to the
You can also set
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;
orderdetermines which elements have predecence along the
flex-directionaxis (similar to
flex-growdetermines whether an element can expand to fill free space
flex-shrinkdetermines whether an element can shrink to make space for other children
flex-basissets the base size of an element before it grows/shrinks
align-selfallows the child element to override the value set in the parent
align-itemsfor a specific element
You can also set
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.
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
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.
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.
A simple flexible grid of small and large items, constructed using
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.
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.
A few resources I've found helpful when learning and using flexbox: