Concept
Flexbox (Flexible Box Layout) is a one-dimensional layout model, it distributes space and aligns items along a single axis at a time (a row, or a column). This is the key distinction from Grid, which is two-dimensional (rows and columns simultaneously). The practical rule of thumb: reach for flexbox when laying out items in a line (a nav bar, a button group, a card's internal content, centering something), reach for Grid when you need to control both rows and columns together (a page layout, a photo gallery, a dashboard).
The two axes, the single most important mental model
.container {
display: flex;
flex-direction: row; /* default: main axis is horizontal */
}Every flex property is defined relative to one of two axes, and which axis is "main" depends entirely on flex-direction:
- Main axis, the direction items are laid out (
row= horizontal,column= vertical). - Cross axis, perpendicular to the main axis.
.container { flex-direction: row; } /* main = horizontal, cross = vertical */
.container { flex-direction: column; } /* main = vertical, cross = horizontal */justify-content always controls the main axis. align-items/align-content always control the cross axis. This single fact resolves 90% of "why isn't my centering working" confusion, if you set flex-direction: column and use justify-content: center expecting horizontal centering, it won't work, because in a column, justify-content is now controlling vertical space.
/* Perfect centering, both axes, regardless of direction */
.container {
display: flex;
justify-content: center; /* main axis */
align-items: center; /* cross axis */
}CSS Box Model Inspector
Generated CSS
/* Container Styles */
.container {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
flex-wrap: nowrap;
gap: 12px;
padding: 16px;
margin: 8px;
border: 2px solid #6366f1;
box-sizing: border-box;
}Container properties
.container {
display: flex;
flex-direction: row | row-reverse | column | column-reverse;
flex-wrap: nowrap | wrap | wrap-reverse;
justify-content: flex-start | flex-end | center | space-between | space-around | space-evenly;
align-items: stretch | flex-start | flex-end | center | baseline;
align-content: /* same values as justify-content, only matters with flex-wrap + multiple lines */
gap: 1rem; /* modern, preferred over margin hacks for spacing between items */
justify-content: space-between vs space-around vs space-evenly is a common point of confusion:
space-between, no space at the container edges, equal space between items.space-around, equal space around each item (so edge gaps are half the between-item gap).space-evenly, truly equal space everywhere, including edges.
Item properties, the flex-grow/shrink/basis triad
.item {
flex-grow: 0; /* how much this item grows relative to siblings when there's extra space */
flex-shrink: 1; /* how much this item shrinks relative to siblings when space is tight */
flex-basis: auto; /* the item's starting size before growing/shrinking is applied */
/* shorthand, almost always what you actually want to write */
flex: 0 1 auto; /* grow shrink basis */
}flex-basis is not the same as width. flex-basis sets the starting point for space distribution along the main axis; the browser then applies flex-grow/flex-shrink on top of it. If flex-direction: column, flex-basis controls the starting height, not width, another axis-relativity gotcha.
Common shorthand patterns:
.item { flex: 1; } /* flex: 1 1 0%, grow and shrink equally, ignore content size, "take equal share" */
.item { flex: auto; } /* flex: 1 1 auto, grow and shrink, but starting from content size */
.item { flex: none; } /* flex: 0 0 auto, rigid, never grows or shrinks */
.item { flex: 0 0 200px; } /* fixed 200px, never grows or shrinks */flex: 1 (equal-share items ignoring their content's natural size) and flex: auto (starts from content size, then grows/shrinks) look similar but produce different results when items have different amounts of content, this distinction trips people up constantly.
align-self, per-item cross-axis override
.item {
align-self: flex-start | flex-end | center | baseline | stretch; /* overrides the container's align-items for this one item */
}order, visual reorder without touching the DOM
.item-3 { order: -1; } /* moves visually first, without changing DOM/tab order */Important: order only changes visual order, it does not change DOM order, tab order, or reading order for screen readers. Using it to reorder content in a way that no longer matches the visual flow creates exactly the keyboard/screen-reader mismatch covered in the Accessibility topic, a sighted keyboard user tabbing through will jump in an order that doesn't match what they see.
Common patterns
/* Perfect centering (both axes) */
.center { display: flex; justify-content: center; align-items: center; }
/* Nav bar: logo left, links right */
.nav { display: flex; justify-content: space-between; align-items: center; }
/* Equal-width columns */
.columns { display: flex; }
.columns > * { flex: 1; }
/* Sticky footer (footer stays at bottom even with little content) */
body { display: flex; flex-direction: column; min-height
Common Mistakes
1. Confusing which axis justify-content vs align-items controls
Covered above, the #1 flexbox confusion. Remember: main axis = justify-content, cross axis = align-items, and which is which flips with flex-direction.
2. Using margin for gaps instead of gap
/* Old workaround, extra margin on every item except the last, fragile */
.item:not(:last-child) { margin-right: 1rem; }
/* Modern, just this */
.container { display: flex; gap: 1rem; }gap (broadly supported in flexbox since ~2021) is simpler, doesn't need :last-child exceptions, and correctly handles flex-wrap (spacing between wrapped rows too, which margin-based approaches handle awkwardly).
3. Expecting flex: 1 and flex: auto to behave the same
<div style="display:flex">
<div style="flex: 1">Short</div>
<div style="flex: 1">A much longer piece of content here</div>
</div>With flex: 1, both items end up equal width regardless of content length (content size is ignored as the basis). With flex: auto instead, the longer item's natural content size influences its starting width before grow/shrink is applied, so they won't necessarily end up equal. Pick deliberately based on which behavior you actually want.
4. Setting a fixed width on a flex item and being surprised it still shrinks
.item { width: 200px; } /* flex-shrink defaults to 1, this can still shrink below 200px */flex-shrink: 1 is the default, a flex item with only width set (no flex-shrink: 0) will still shrink if the container is tight on space. If you need a genuinely fixed size, use flex: 0 0 200px or add flex-shrink: 0 explicitly.
5. Using order to fix a visual layout mistake instead of the source markup order
Reordering via CSS order when the correct fix is reordering the actual DOM creates a silent accessibility mismatch (see Concept section), reserve order for genuinely presentation-only reordering (e.g. a "featured" card visually first on desktop but not meaningfully different in importance), not as a patch for wrong source order.
6. Forgetting min-width: 0 on flex items containing text/long content
/* A flex item won't shrink below its content's intrinsic minimum size by default,
which can cause overflow with long unbreakable text (URLs, long words) */
.item { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }Flex items have an implicit min-width: auto (roughly, "don't shrink smaller than my content needs"), which can prevent text truncation (text-overflow: ellipsis) from working until you explicitly override it with min-width: 0.
Best Practices
- Identify the main axis first (
flex-direction), then reason aboutjustify-content/align-itemsrelative to it, don't guess. - Use
gapfor spacing between items, not margin hacks. - Choose
flex: 1vsflex: autovsflex: nonedeliberately based on whether content size should influence the starting size. - Add
flex-shrink: 0(or use theflexshorthand) for anything that must never shrink, icons, avatars, fixed-width sidebars.
Further Resources
- MDN, Flexbox
- CSS-Tricks, A Complete Guide to Flexbox, the most-referenced visual guide on the web.
- Flexbox Froggy, interactive game for learning flexbox properties.
- web.dev, Flexbox
- Josh W. Comeau, An Interactive Guide to Flexbox
