CSS Flexbox: Interactive Guide
Adjust a live flex container's properties with up to six boxes and watch the generated CSS update in real time, ready to copy into your own stylesheet.
Published Last reviewed
The Flexbox Model
Setting display: flex on a container turns its direct children
into flex items laid out along a main axis,
horizontal by default. Everything flexbox does is described in terms of that
main axis and the cross axis running perpendicular to it; the
five properties below all just position items along one or the other.
flex-direction is what decides which axis is which: in
row the main axis runs left to right and the cross axis runs top
to bottom; switch to column and that flips, the main axis becomes
vertical. Every other property below keeps the same meaning either way, since
they're defined relative to the main/cross axes, not literally to "horizontal"
and "vertical."
Live Demo
Container Properties
These five properties (plus display: flex itself) all live on the
container, not the items, and correspond directly to the
dropdowns in the demo above:
| Property | What it controls |
|---|---|
| flex-direction | Which way the main axis runs: row, row-reverse, column, or column-reverse. The -reverse variants flip the visual order without touching the underlying source order or the order property. |
| justify-content | Spacing of items along the main axis: bunched at the start or end, centered, or spread out with space-between (no space at the outer edges), space-around (equal space around each item, so edge gaps are half-size), or space-evenly (every gap, including the edges, is the same size). |
| align-items | Positioning of items along the cross axis. stretch (the default) makes every item fill the cross-axis size unless it has an explicit height/width set on that axis. Because the demo's boxes have a fixed 64px width and height, switching to stretch changes nothing visible here. Remove a box's cross-axis size and it would fill the container's height (in a row) or width (in a column). |
| flex-wrap | nowrap (the default) forces every item onto one line, shrinking them if they don't fit. wrap lets items overflow onto additional lines instead. |
| gap | Fixed spacing between items, on both axes. Modern and the preferred approach; the older alternative was margin tricks on individual items, which got messy fast once wrapping was involved. |
Try switching flex-direction to column in the demo,
then changing align-items: instead of moving boxes up and down,
it now moves them left and right, because the cross axis rotated along with
the main axis.
Item Properties: order, flex, and align-self
The container properties in Section 3 apply to every item at once. A handful
of properties go the other way: set on an individual item, they override how
that one item behaves within the container's layout. order is the
one used by the live demo above.
.box-3 { order: -1; /* visually first, regardless of where it sits in the HTML */ }
Every flex item has a default order of 0. Items are
laid out by sorting on order first, and falling back to source
(HTML) order for any items that tie, which is why two untouched boxes (both
still at the default 0) stay in their original relative order even
after a third box elsewhere gets pulled to the front with a negative value.
Critically, order changes only the visual position; it
doesn't move anything in the DOM, doesn't change tab order for keyboard
navigation, and doesn't change how a screen reader announces the content, which
makes it purely a visual layout tool and a poor substitute for actually
reordering meaningful content in the markup.
Often written together as the flex shorthand, these three control
how an item's size responds to the container having extra or insufficient
space. flex-basis is the item's starting size before any
growing/shrinking happens; flex-grow is a ratio describing how
much of any leftover space the item should claim relative to its
siblings; flex-shrink is the same idea in reverse, how much of a
size deficit the item should absorb when there isn't enough room for
every item at its basis size. flex: 1, by far the most common use,
is shorthand for flex: 1 1 0%: ignore each item's natural content
size and divide the container's space evenly between them.
One sizing gotcha is worth committing to memory: flex items default to
min-width: auto (min-height in a column), which means
an item refuses to shrink below its content's natural size no matter
what flex-shrink says. When something wide and unbreakable (a long
URL, a table, a <pre> block) forces the whole layout to
overflow its container, the fix is min-width: 0 on the flex item.
The same applies to grid items, which is why sizing grid columns with
minmax(0, 1fr) instead of a bare 1fr avoids the
identical overflow.
align-self overrides the container's align-items for
one specific item on the cross axis only, useful for pulling a single item to
the opposite end of the cross axis from all its siblings without having to
restructure the container.
Reference
| Property | Applies to | Default |
|---|---|---|
| display: flex | Container | — |
| flex-direction | Container | row |
| justify-content | Container | flex-start |
| align-items | Container | stretch |
| flex-wrap | Container | nowrap |
| gap | Container | 0 |
| order | Item | 0 |
| flex-grow | Item | 0 |
| flex-shrink | Item | 1 |
| flex-basis | Item | auto |
| align-self | Item | auto (inherits align-items) |