Flexbox
Why you need this
Putting elements in a row, pushing them to the edges, centring them vertically — this used to be agony
with float and tables. Flexbox ("flexible boxes") solves such tasks in a couple of lines. A site
header, a row of cards, buttons in a line, centring anything — that's all flex.
Container and items
Flexbox is turned on for the parent:
<style>
.row { display: flex; }
.row div { padding: 20px; background: gold; }
</style>
<div class="row">
<div>1</div>
<div>2</div>
<div>3</div>
</div>
Result: three yellow blocks in a row, although divs usually stand one under another.
.rowis the flex container;- its direct children are the flex items. Grandchildren don't react to flex.
Two axes
A container has a main axis — the items go along it — and a cross axis at a right angle.
.row { flex-direction: row; } /* main axis → left to right (the default) */
.col { flex-direction: column; } /* main axis ↓ top to bottom */
This matters: the alignment properties work relative to the axes, not "horizontally":
justify-content— along the main axis;align-items— along the cross axis.
justify-content: along the main axis
.row { display: flex; justify-content: space-between; }
| Value | What it does |
|---|---|
flex-start |
everything at the start (the default) |
flex-end |
everything at the end |
center |
in the centre |
space-between |
the first at the start, the last at the end, the rest evenly between |
space-around |
equal space around each item |
space-evenly |
all gaps equal, including the edges |
Result with space-between: block 1 at the left edge, block 3 at the right, block 2 in the middle.
align-items: along the cross axis
.row { display: flex; align-items: center; height: 200px; }
| Value | What it does |
|---|---|
stretch |
stretch to the full height (the default) |
flex-start / flex-end |
push to the start / to the end |
center |
in the centre |
Result: the blocks stand in the middle of the 200-pixel container's height.
Perfect centring — something the web lacked for a long time:
.screen {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
Result: the content is exactly in the centre of the screen, both horizontally and vertically.
gap: spacing
.row { display: flex; gap: 16px; }
Result: 16px between the items — but not at the edges. People used to give every item a margin and
then remove it from the last one; gap is simpler.
flex-wrap: wrapping
By default flex items shrink just to fit in one line. To make them wrap:
.cards { display: flex; flex-wrap: wrap; gap: 10px; }
.cards div { width: 200px; }
Result: 200px cards in a row; the ones that don't fit go to the next line. A narrow screen gets one column, a wide one gets four.
Item properties: flex-grow, flex-shrink, flex-basis
These properties are set on the children:
flex-basis— the "desired" size along the main axis;flex-grow— what share of the free space to take (0 — don't grow);flex-shrink— whether it may shrink when space is short (0 — it may not).
.sidebar { flex: 0 0 250px; } /* don't grow, don't shrink, 250px */
.main { flex: 1; } /* take all the free space */
Result: the sidebar is exactly 250px, and the main part stretches over all the remaining width.
The shorthand is flex: grow shrink basis. If two items have flex: 1 and flex: 2, the second gets
twice as much free space.
A single item can get its own cross alignment: align-self: flex-end;.
And margin-left: auto on an item "pushes" it to the right edge.
How it works inside
The browser first places the items by their flex-basis (or content width), then counts how much
space is left. If there is space, it shares it by flex-grow; if there isn't enough, it takes it away
by flex-shrink. Then it lays out the items along the main axis by justify-content and aligns them
across by align-items.
Common mistakes
display: flexon the items, not the container. Flex is turned on for the parent.- Expecting it to work on grandchildren. Flex only affects direct children. A nested row is another flex container.
- Mixing up the axes. With
flex-direction: column,justify-contentworks vertically, andalign-itemshorizontally. align-items: center"doesn't work". The container is no taller than its content — there's nothing to centre in.- The cards got squashed. Without
flex-wrap: wrapthe items shrink into one line.
Cheat sheet
| Property (on whom) | What it does |
|---|---|
display: flex (parent) |
turn on flexbox |
flex-direction: row / column |
the direction of the main axis |
justify-content |
alignment along the main axis |
align-items |
alignment along the cross axis |
gap: 16px |
gaps between items |
flex-wrap: wrap |
wrap onto a new line |
flex: 1 (child) |
take the free space |
flex: 0 0 200px (child) |
a fixed size |
align-self (child) |
its own cross alignment |