CSS Flexbox: The Only Guide You Actually Need
A practical flexbox tutorial focused on the mental model and the properties you'll use every day, with common layout patterns.
Flexbox has been around for over a decade now and it's still the most useful layout tool in CSS. Grid is great for two-dimensional layouts, but for most day-to-day work -- navbars, card rows, centering things, spacing items -- flexbox is what you reach for.
The Mental Model
Everything in flexbox comes down to two axes:
- Main axis: the direction items flow (horizontal by default)
- Cross axis: perpendicular to the main axis (vertical by default)
display: flex on a container, its children become flex items that line up along the main axis. That's it. Every flexbox property is about controlling how items are placed, sized, and spaced along these two axes.
flex-direction sets which axis is "main":
row(default): main axis is horizontal, left to rightcolumn: main axis is vertical, top to bottomrow-reverseandcolumn-reverse: same but flipped
The Properties That Matter
On the Container (Parent)
justify-content -- controls spacing along the main axis.
.container {
display: flex;
justify-content: space-between; / items pushed to edges, equal space between /
}
The values you'll actually use:
flex-start(default) -- items packed to the startcenter-- items centeredspace-between-- first item at start, last at end, equal gaps betweenspace-evenly-- equal space everywhere, including edgesflex-end-- items packed to the end
align-items -- controls alignment along the cross axis.
.container {
display: flex;
align-items: center; / vertically centers items (when direction is row) /
}
The values you'll use:
stretch(default) -- items stretch to fill the container's cross-axiscenter-- items centered on the cross axisflex-start/flex-end-- items aligned to start/end of cross axis
gap -- space between items. This replaced the old hack of using margins.
.container {
display: flex;
gap: 16px;
}
Clean, simple, no weird margin-collapsing behavior. Use it.
flex-wrap -- whether items can wrap to the next line.
.container {
display: flex;
flex-wrap: wrap;
}
Without this, flex items will shrink to fit on one line no matter what. Set wrap when you want items to flow to the next row.
On the Items (Children)
flex-grow -- how much an item should grow relative to siblings.
.sidebar { flex-grow: 0; } / don't grow /
.content { flex-grow: 1; } / take all remaining space /
flex-shrink -- how much an item should shrink when space is tight. Default is 1 (items shrink equally). Set to 0 if an item should never shrink.
flex-basis -- the starting size before grow/shrink kicks in. Think of it as a "suggested width" (or height, if direction is column).
The shorthand flex combines all three:
.item { flex: 1; } / grow: 1, shrink: 1, basis: 0 /
.item { flex: 0 0 300px; } / don't grow, don't shrink, always 300px /
align-self -- override align-items for a single item.
Common Layout Patterns
Centering (The Classic)
.center-me {
display: flex;
justify-content: center;
align-items: center;
height: 100vh; / or whatever height /
}
Two lines of actual layout code. This is the reason flexbox exists.
Navbar with Logo Left, Links Right
.navbar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 24px;
}
Logo on the left, navigation links on the right. No floats, no positioning hacks.
Card Grid That Wraps
.card-grid {
display: flex;
flex-wrap: wrap;
gap: 20px;
}
.card {
flex: 0 0 calc(33.333% - 14px); / 3 columns with gap accounted for /
}
For truly responsive grids, CSS Grid with auto-fill / minmax is better. But this flexbox approach works fine for simpler cases.
Sticky Footer Layout
body {
display: flex;
flex-direction: column;
min-height: 100vh;
}
main {
flex: 1; / main content grows to fill available space /
}
footer {
/ footer stays at the bottom naturally /
}
The flex: 1 on main makes it absorb all the leftover vertical space, pushing the footer down.
Input with Button
.search-bar {
display: flex;
}
.search-bar input {
flex: 1; / input grows to fill space /
}
.search-bar button {
flex: 0 0 auto; / button stays its natural size /
}
Properties You Can Mostly Ignore
order-- reorders items visually. Breaks tab order and accessibility. Rearrange your HTML instead.align-content-- only matters when you have wrapping items AND extra space on the cross axis. Rare.flex-flow-- shorthand forflex-direction+flex-wrap. Just write them separately; it's more readable.
Debugging Flexbox
Browser DevTools are your best friend here. In Chrome and Firefox, when you select a flex container in the Elements panel, you'll see a "flex" badge. Click it to get a visual overlay showing the axes, gaps, and how space is distributed.
If something isn't working:
- Check that the parent has
display: flex(not the child) - Check
flex-direction-- your "horizontal" property might actually be controlling the vertical axis - Check if items are overflowing because you forgot
flex-wrap: wrap - Check if
flex-basisor awidth/min-widthis overriding what you expect
Practice
Flexbox is one of those things where reading about it gets you 30% of the way and actually building layouts gets you the rest. Open CodeUp, fire up the CSS exercises, and build these patterns from scratch. Once you've centered a div with flexbox a dozen times, it becomes second nature.