Flexbox turns a one-dimensional layout (a row or column) into something you can control precisely — space distribution, alignment, wrapping, and order — without floats, hacks, or position: absolute everywhere. Once you internalise the twelve core properties, you rarely need anything else for UI layout.
This cheat sheet covers every property with live code, common patterns, and the mistakes that catch even experienced developers.
How flexbox works
There are two players: the flex container (the parent) and flex items (the direct children).
<div class="container"> <!-- flex container -->
<div class="item">A</div>
<div class="item">B</div>
<div class="item">C</div>
</div>
.container {
display: flex; /* turns children into flex items */
}
Properties on the container control the overall layout. Properties on items control individual behaviour.
Container properties
flex-direction
Sets the main axis — the direction items are placed.
| Value | Direction |
|---|---|
row (default) |
Left → right |
row-reverse |
Right → left |
column |
Top → bottom |
column-reverse |
Bottom → top |
.container { flex-direction: column; }
flex-wrap
By default, items squeeze onto one line. flex-wrap lets them wrap.
| Value | Behaviour |
|---|---|
nowrap (default) |
All items on one line |
wrap |
Items wrap to the next line |
wrap-reverse |
Items wrap to the previous line |
.container { flex-wrap: wrap; }
flex-flow (shorthand)
.container { flex-flow: row wrap; }
/* shorthand for flex-direction + flex-wrap */
justify-content
Aligns items along the main axis (row = horizontal, column = vertical).
| Value | Effect |
|---|---|
flex-start (default) |
Pack at start |
flex-end |
Pack at end |
center |
Centre |
space-between |
Equal gaps between items, none at edges |
space-around |
Equal gaps around each item (half-gap at edges) |
space-evenly |
Equal gaps everywhere including edges |
.container { justify-content: space-between; }
align-items
Aligns items along the cross axis (perpendicular to the main axis).
| Value | Effect |
|---|---|
stretch (default) |
Items fill the container height |
flex-start |
Items align to the start of the cross axis |
flex-end |
Items align to the end |
center |
Items centred on the cross axis |
baseline |
Items align by their text baseline |
.container { align-items: center; }
align-content
Like align-items, but for multiple lines (only works when flex-wrap: wrap and there are multiple rows/columns).
Values mirror justify-content: flex-start, flex-end, center, space-between, space-around, space-evenly, stretch.
.container {
flex-wrap: wrap;
align-content: space-between;
}
gap
Adds gutters between items — cleaner than margin hacks.
.container {
display: flex;
gap: 16px; /* row-gap and column-gap */
gap: 16px 24px; /* row-gap column-gap */
}
gapworks for both flexbox and grid — it's the modern replacement formargintricks.
Item properties
flex-grow
How much an item expands to fill available space. Default 0 (don't grow).
.item-a { flex-grow: 1; } /* takes all available space */
.item-b { flex-grow: 2; } /* takes twice as much as item-a */
flex-shrink
How much an item shrinks when there's not enough space. Default 1 (shrink equally). Set 0 to prevent shrinking.
.logo { flex-shrink: 0; } /* never shrink the logo */
flex-basis
The initial size of an item before growing or shrinking. Can be a length (200px, 50%) or auto (use the item's content size).
.sidebar { flex-basis: 250px; }
flex (shorthand)
The most important shorthand — covers flex-grow, flex-shrink, flex-basis in one declaration.
.item { flex: 1; } /* grow: 1, shrink: 1, basis: 0 */
.item { flex: 1 0 200px; } /* grow: 1, shrink: 0, basis: 200px */
.item { flex: auto; } /* 1 1 auto */
.item { flex: none; } /* 0 0 auto — rigid size */
Prefer
flex: 1overflex-grow: 1— the shorthand also setsflex-basis: 0which gives more predictable equal sizing.
align-self
Override align-items for one specific item.
.special { align-self: flex-end; }
Values: same as align-items.
order
Change the visual order without changing the HTML. Default 0.
.first { order: -1; } /* appears before items with order 0 */
.last { order: 99; }
Changing
orderaffects visual presentation but not DOM order — screen readers still read the original HTML order.
Quick reference table
| Property | On | Default | Purpose |
|---|---|---|---|
flex-direction |
Container | row |
Main axis direction |
flex-wrap |
Container | nowrap |
Line wrapping |
justify-content |
Container | flex-start |
Main axis alignment |
align-items |
Container | stretch |
Cross axis alignment (single line) |
align-content |
Container | stretch |
Cross axis alignment (multi-line) |
gap |
Container | 0 |
Gutters between items |
flex-grow |
Item | 0 |
Growth factor |
flex-shrink |
Item | 1 |
Shrink factor |
flex-basis |
Item | auto |
Initial size |
flex |
Item | 0 1 auto |
Shorthand for above three |
align-self |
Item | auto |
Override cross-axis alignment |
order |
Item | 0 |
Visual ordering |
Common patterns
1 — Perfect centering
.container {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
2 — Navigation bar
.nav {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 24px;
}
.nav-logo { flex-shrink: 0; }
.nav-links { display: flex; gap: 16px; }
3 — Sidebar + main layout
.layout {
display: flex;
gap: 24px;
}
.sidebar {
flex: 0 0 260px; /* fixed width, won't grow or shrink */
}
.main {
flex: 1; /* takes remaining space */
}
4 — Equal-width card grid
.cards {
display: flex;
flex-wrap: wrap;
gap: 16px;
}
.card {
flex: 1 1 280px; /* grow/shrink, but never narrower than 280px */
}
5 — Sticky footer
body {
display: flex;
flex-direction: column;
min-height: 100vh;
}
main {
flex: 1; /* pushes footer to bottom */
}
6 — Inline icon + text alignment
.badge {
display: inline-flex;
align-items: center;
gap: 6px;
}
Common mistakes
Using flex vs flex-grow — flex: 1 sets flex-basis: 0 so all items start from zero and divide space equally. flex-grow: 1 leaves flex-basis: auto, so items first take their content size, then divide the remainder — results differ.
Forgetting min-width: 0 — flex items have min-width: auto by default, which prevents them from shrinking below their content size. Long words or code blocks can overflow. Fix:
.item { min-width: 0; overflow: hidden; }
align-content doing nothing — only activates with flex-wrap: wrap and multiple lines. On a single-line container it has no effect.
justify-items doesn't exist in flexbox — that's a grid property. Use justify-content for the container or margin-left: auto on an individual item.
order and accessibility — visual reordering with order can confuse keyboard navigation (Tab follows DOM order, not visual order). Use it sparingly.
JavaScript reference
Read and set flex properties dynamically:
const el = document.querySelector('.container');
// Read
getComputedStyle(el).justifyContent; // "flex-start"
// Set
el.style.flexDirection = 'column';
el.style.gap = '16px';
FAQ
When should I use flexbox vs grid? Flexbox is one-dimensional: a single row or column. CSS Grid is two-dimensional: rows and columns simultaneously. Use flexbox for navigation bars, button groups, and card rows. Use grid for page-level layouts and overlapping elements.
Does flexbox work in all browsers?
Yes — display: flex has 99%+ global browser support. gap for flexbox requires Chrome 84+, Firefox 63+, Safari 14.1+. All modern browsers are fine; IE 11 had a broken implementation that can be avoided.
Why isn't space-between working?
It distributes extra space between items. If you only have one item, or if items fill the container exactly, there's no extra space to distribute. Try justify-content: space-evenly or add flex-wrap: wrap so multiple rows appear.
How do I make a flex item ignore the parent's align-items?
Use align-self on the item: align-self: flex-start will override the container's align-items: center.
Can I nest flexbox containers? Yes — any flex item can itself be a flex container. Common pattern: outer container uses column direction, inner cards use row direction.
What's the difference between gap and margin?
gap only adds space between items, never on the outer edges. margin adds space around every side. gap is simpler and doesn't require negative margins on the container to compensate for edge gaps.