Flexbox is a one-dimensional layout model organised around a main axis and a cross axis. You set display:flex on the container, pick the main axis direction with flex-direction, align along it with justify-content, align across it with align-items, and control how children absorb leftover space with flex-grow, flex-shrink and flex-basis.
Last updated: 2026-09-17 · Based on CSS Flexible Box Layout Module Level 1, supported in all current browsers
Flexbox is the layout model most people reach for first, and for good reason. But a lot of the confusion around it comes from treating it as a bag of properties to memorise rather than as a model with two axes.
This is the English companion to the Chinese original. Same content, written for English readers.
Before Flexbox
Laying things out used to mean combining several techniques that were never designed for layout:
- Normal flow — inline elements run left to right, block elements stack top to bottom.
- float + clear — the standard way to get two or three columns, at the cost of clearing hacks and collapsed parent heights.
- position: relative + absolute — precise, but the element leaves the flow entirely.
- display: inline-block — horizontal rows, with the infamous whitespace gap between items.
- Negative margins — for pulling elements around.
Flexbox replaced most of these for one-dimensional arrangements.
The mental model: two axes
An element with display: flex becomes a flex container; its direct children become flex items.
The container has two axes. The main axis is the one items line up along — horizontal by default. The cross axis runs perpendicular to it. Every alignment property belongs to one axis or the other, and flex-direction decides which is which.
That single fact resolves most Flexbox confusion. justify-content is not “horizontal alignment”; it is “main axis alignment”. Switch flex-direction to column and it becomes vertical.
Container properties
| Property | What it controls |
|---|---|
flex-direction |
Which way the main axis points (row, row-reverse, column, column-reverse) |
flex-wrap |
Whether items overflow onto new lines |
flex-flow |
Shorthand for the two above |
justify-content |
Alignment along the main axis |
align-items |
Alignment along the cross axis, per line |
align-content |
Alignment of the lines themselves, only relevant when wrapping |
Item properties
| Property | What it controls |
|---|---|
order |
Visual position, without changing the DOM |
flex-grow |
Share of leftover space this item absorbs |
flex-shrink |
How much this item gives up when space runs short |
flex-basis |
The item’s starting size before growing or shrinking |
flex |
Shorthand for grow / shrink / basis |
align-self |
Overrides align-items for this one item |
How flex-grow actually distributes space
This is the part worth getting precise about. The browser first lays items out at their flex-basis, then measures the leftover space in the container, then hands out that leftover in proportion to each item’s flex-grow value.
So flex-grow: 2 does not make an item twice as wide as a flex-grow: 1 sibling. It makes it absorb twice as much of the leftover. If the items started at different basis sizes, the final widths are not in a 2:1 ratio.
When you want genuinely equal columns, use flex: 1 on all of them — the flex-basis: 0% in that shorthand zeroes out the starting sizes, so the leftover is the entire container and the proportions work out cleanly.
Where Flexbox is the wrong tool
Flexbox is one-dimensional. A card grid where the last row must align left is the classic case where it fights back: you end up padding the list with invisible elements or computing margins by hand. Grid solves it in two lines because it genuinely understands rows and columns.
The rule of thumb: do you need to control rows and columns at the same time? If yes, Grid. If no, Flexbox.
Further reading
The Chinese original of this article covers the same ground with additional code samples: Flex 布局.
Frequently asked questions
When should I use Flexbox instead of CSS Grid?
Flexbox handles one axis at a time — a row or a column. Grid handles rows and columns together. Use Flexbox for arranging things inside a component (navigation bars, button groups, centring). Use Grid for page skeletons and card grids where you need to control both dimensions.
What does flex: 1 actually mean?
It is shorthand for flex-grow: 1, flex-shrink: 1, flex-basis: 0%. The item can grow and shrink, and its base size is treated as zero when distributing space — which is why several flex:1 siblings end up equal width regardless of their content.
Why is the width I set on a flex item being ignored?
Because flex-basis takes precedence over width. When flex-basis is anything other than auto, it wins. Either set flex-basis: auto so width applies, or drop width and size the item with flex-basis directly.
Does justify-content always control horizontal alignment?
No. It controls alignment along the main axis, and the main axis direction comes from flex-direction. With the default row it is horizontal; switch to column and justify-content becomes vertical while align-items becomes horizontal.





