CSS Flexbox: The Complete Guide to Flexible Layouts
June 10, 2026 · 6 min read
CSS Flexbox: The Complete Guide to Flexible Layouts
CSS Flexbox (Flexible Box Layout) is one of the most useful tools in a frontend developer's toolkit. It solves layout problems that used to require float hacks, table tricks, or JavaScript — things like centering an element both vertically and horizontally, distributing space between items, or building a responsive nav bar. This guide walks through every key Flexbox concept with real code you can use today.
If you want to experiment without writing code from scratch, try the CSS Flexbox Generator to build and export layouts visually. And once you've mastered Flexbox, check out the CSS Grid Guide for two-dimensional layouts.
Enabling Flexbox: display: flex
To activate Flexbox, set display: flex on a container element. All direct children immediately become flex items.
.container {
display: flex;
}
That one line turns the container into a flex context. The children line up in a row by default. Use display: inline-flex if you need the container itself to behave like an inline element.
flex-direction: Controlling the Main Axis
Flexbox works along two axes: the main axis (direction items flow) and the cross axis (perpendicular to it). flex-direction sets the main axis.
.container {
display: flex;
flex-direction: row; /* default: left to right */
flex-direction: row-reverse; /* right to left */
flex-direction: column; /* top to bottom */
flex-direction: column-reverse;
}
When you switch to column, everything that applied to the horizontal axis now applies vertically. This trips up a lot of developers early on.
justify-content: Alignment on the Main Axis
justify-content controls how items are distributed along the main axis.
.container {
display: flex;
justify-content: flex-start; /* default */
justify-content: flex-end;
justify-content: center;
justify-content: space-between; /* gaps between items only */
justify-content: space-around; /* equal space around each item */
justify-content: space-evenly; /* equal space between items and edges */
}
space-between is the go-to for nav bars where you want the logo on the left and links on the right.
align-items: Alignment on the Cross Axis
align-items aligns items along the cross axis (perpendicular to main axis).
.container {
display: flex;
align-items: stretch; /* default: items fill the container height */
align-items: flex-start;
align-items: flex-end;
align-items: center;
align-items: baseline; /* align by text baseline */
}
Centering a Div: The Classic Problem Solved
Centering something both horizontally and vertically used to be a running joke in CSS. With Flexbox:
.container {
display: flex;
justify-content: center;
align-items: center;
height: 100vh; /* or any fixed height */
}
That's it. The child element is perfectly centered regardless of its size.
flex-wrap: Handling Overflow
By default, flex items try to fit on one line and shrink to do so. flex-wrap lets them wrap to new lines instead.
.container {
display: flex;
flex-wrap: wrap; /* wrap to new lines */
flex-wrap: nowrap; /* default: no wrapping */
flex-wrap: wrap-reverse;
}
gap: Spacing Between Items
The gap property (previously grid-gap, now works in Flexbox too) adds space between flex items without affecting outer edges.
.container {
display: flex;
flex-wrap: wrap;
gap: 16px; /* row and column gap */
gap: 16px 24px; /* row gap, column gap */
}
This is cleaner than using margin on individual items and avoids the "extra margin on the last item" problem.
flex-grow, flex-shrink, flex-basis
These three properties control how individual items size themselves relative to available space.
flex-grow— how much an item grows to fill extra space (default: 0)flex-shrink— how much an item shrinks when space is tight (default: 1)flex-basis— the item's starting size before growing/shrinking (default: auto)
/* shorthand: flex: grow shrink basis */
.item {
flex: 1; /* grow: 1, shrink: 1, basis: 0 — equal-width columns */
flex: 0 0 200px; /* fixed 200px, won't grow or shrink */
flex: 2; /* grows twice as fast as flex: 1 siblings */
}
The flex: 1 shorthand is incredibly useful for making columns share space equally.
order: Reordering Items Visually
You can reorder flex items visually without changing the HTML source order:
.first { order: -1; } /* moves to front */
.last { order: 99; } /* moves to end */
/* default order: 0 */
This is handy for responsive reordering — putting a sidebar above the main content on mobile without touching the DOM.
align-self: Per-Item Cross-Axis Alignment
While align-items applies to all children, align-self overrides alignment for a single item:
.special-item {
align-self: flex-end; /* overrides the container's align-items */
}
Real Example: Navigation Bar
.navbar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 24px;
height: 60px;
}
.nav-links {
display: flex;
gap: 24px;
list-style: none;
}
<nav class="navbar">
<a class="logo" href="/">Brand</a>
<ul class="nav-links">
<li><a href="/about">About</a></li>
<li><a href="/blog">Blog</a></li>
<li><a href="/contact">Contact</a></li>
</ul>
</nav>
Real Example: Responsive Card Grid
.card-grid {
display: flex;
flex-wrap: wrap;
gap: 20px;
}
.card {
flex: 1 1 280px; /* grow and shrink, but start at 280px */
border: 1px solid #e2e8f0;
border-radius: 8px;
padding: 20px;
}
Cards fill the row and wrap naturally. When the viewport narrows below 280px * 2 + gap, cards stack to a single column — no media queries needed.
Real Example: Sidebar Layout
.page {
display: flex;
min-height: 100vh;
}
.sidebar {
flex: 0 0 260px; /* fixed width sidebar */
}
.main-content {
flex: 1; /* takes all remaining space */
padding: 24px;
}
Common Gotchas
Gotcha 1: flex-direction: column swaps the axes. When direction is column, justify-content aligns vertically and align-items aligns horizontally — the opposite of the row direction. Many developers forget this swap.
Gotcha 2: Percentage heights need a height on the parent. If you set height: 100% on a flex item but the container has no explicit height, it won't work. Use min-height or set a height on the container.
Gotcha 3: flex: 1 on images can distort them. If you apply flex: 1 to an <img>, add min-width: 0 and object-fit: cover to prevent stretching.
Gotcha 4: Margins don't collapse in flex containers. Unlike block layout, adjacent flex items don't collapse their margins. Use gap instead of margin for consistent spacing.
Gotcha 5: flex-basis vs width. In a flex row, flex-basis takes precedence over width. In a flex column, it takes precedence over height. Use flex-basis explicitly when you mean "starting size".
Quick Reference
| Property | Applies To | What It Does |
|---|---|---|
display: flex |
Container | Enables flex layout |
flex-direction |
Container | Sets main axis direction |
justify-content |
Container | Main axis alignment |
align-items |
Container | Cross axis alignment (all items) |
align-content |
Container | Cross axis alignment (multiple rows) |
flex-wrap |
Container | Allow/prevent line wrapping |
gap |
Container | Space between items |
flex-grow |
Item | Growth factor |
flex-shrink |
Item | Shrink factor |
flex-basis |
Item | Starting size |
order |
Item | Visual order |
align-self |
Item | Cross axis alignment (single item) |
Building Layouts Faster
Rather than manually tweaking values, use the CSS Flexbox Generator to configure container and item properties visually and copy the generated CSS directly into your project. It's especially useful for getting justify-content and align-items combinations right at a glance.
For layouts that require both rows and columns at once — like a full page dashboard or a magazine-style grid — Flexbox alone starts to feel awkward. That's when you want CSS Grid, which was purpose-built for two-dimensional layout.