Flexbox Fundamentals
Flex container vs items, main vs cross axis, grow/shrink/basis, alignment, wrapping, and the bugs that show up in real layouts.
- css
- flexbox
- layout
Flexbox is a one-dimensional layout model: you distribute space along a row or a column, then optionally wrap. Grid is two-dimensional. Most nav bars, toolbars, card footers, and form rows are flex problems — not grid problems.
Docs: MDN Flexbox, web.dev Learn CSS — Flexbox.
Container vs items
.toolbar {
display: flex; /* children become flex items */
flex-direction: row; /* main axis → horizontal */
gap: 0.75rem; /* preferred over margin hacks */
}
- Flex container — the element with
display: flexorinline-flex - Flex items — its in-flow children (not absolutely positioned descendants)
Only direct children are flex items. Nested structures need their own flex/grid contexts.
Main axis and cross axis
flex-direction |
Main axis | Cross axis |
|---|---|---|
row (default) |
left → right | top → bottom |
row-reverse |
right → left | top → bottom |
column |
top → bottom | left → right |
column-reverse |
bottom → top | left → right |
Every alignment property is relative to these axes. Memorize “main vs cross,” not only “horizontal vs vertical.”
.stack {
display: flex;
flex-direction: column;
gap: 1rem;
}
Distributing free space on the main axis
.nav {
display: flex;
justify-content: space-between; /* main-axis packing */
align-items: center; /* cross-axis alignment of items */
}
justify-content common values: flex-start | flex-end | center | space-between | space-around | space-evenly.
align-items (cross axis, one line): stretch (default) | flex-start | flex-end | center | baseline.
Per-item override: align-self.
<header class="nav">
<a class="logo" href="/">Frontend Beauty</a>
<nav class="links">…</nav>
<button type="button">Sign in</button>
</header>
.nav {
display: flex;
align-items: center;
gap: 1rem;
}
.links {
display: flex;
gap: 1rem;
margin-inline-start: auto; /* push remaining items to the end */
}
margin: auto on a flex item absorbs free space — often cleaner than nested space-between hacks.
flex-grow, flex-shrink, flex-basis
Shorthand: flex: <grow> <shrink> <basis>
| Property | Role |
|---|---|
flex-basis |
Ideal size before free space is distributed (auto ≈ content/width) |
flex-grow |
Share of extra free space (0 = don’t grow) |
flex-shrink |
Share of deficit when overflowing (0 = don’t shrink) |
.sidebar {
flex: 0 0 240px; /* fixed-ish rail */
}
.main {
flex: 1 1 auto; /* take the rest, can shrink */
min-width: 0; /* critical: allow shrink below content min */
}
The min-width: auto footgun
By default, flex items won’t shrink smaller than their content’s minimum size. Long words / wide tables blow out the layout. Fix:
.main {
flex: 1;
min-width: 0; /* or min-height: 0 in a column flex */
overflow: auto;
}
Same issue appears in nested flex/grid dashboards — if a child won’t scroll, check min-size constraints.
Useful shorthands
flex: 1; /* 1 1 0% — equal flexible columns (basis 0) */
flex: auto; /* 1 1 auto */
flex: none; /* 0 0 auto — size to content, no grow/shrink */
flex: 1 vs flex: auto differs in how basis starts; for equal columns, flex: 1 + min-width: 0 is a common pattern.
Wrapping
.chips {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
With wrap, you get multiple flex lines. Then:
align-contentdistributes lines on the cross axis (notalign-items)align-itemsstill aligns items within each line
.gallery {
display: flex;
flex-wrap: wrap;
align-content: flex-start;
gap: 1rem;
}
Ordering and accessibility
order changes visual order without changing DOM order. Screen readers and tab order follow the DOM. Don’t use order to fix reading order for keyboard users — reorder the markup.
Centering (the meme, correctly)
.center {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
For a single centered child, place-items on grid is also fine. Flex remains ideal when the bar has multiple items with different packing rules.
Flex vs Grid (when to choose)
| Use flex when… | Use grid when… |
|---|---|
| One axis controls the design | Rows and columns matter together |
| Nav, toolbars, media objects | Page scaffolding, card matrices |
| Content-driven item sizes | Explicit tracks (1fr 2fr, areas) |
They compose: a grid cell can be a flex container.
Interview angle
Draw main vs cross for flex-direction: column. Explain flex: 1 and why min-width: 0 fixes overflow. Contrast justify-content vs align-items vs align-content.
Live coding: build a header with logo left, links right, and a wrapping chip list — without absolute positioning.
Related on this site
- CSS Box Model
- Flex grow, shrink, basis
- Flexbox alignment deep dive
- CSS Grid fundamentals
- Centering in CSS
- Cascade & Specificity
Further reading
- MDN: Basic concepts of flexbox
- MDN: Controlling ratios of flex items
- web.dev: Flexbox
- CSS Flexible Box Layout Module Level 1
Related guides
- CSS Grid vs Flexbox When to UseOne-dimensional flex vs two-dimensional grid — decision rules for navs, card grids, page shells, and nested layouts.
- Centering Everything in CSSCenter with flex, grid, margin auto, and inset — horizontal, vertical, and both — plus the absolute-position and text-align traps.
- CSS Box ModelContent, padding, border, margin, box-sizing, and how the math actually works for layout and overflow.
- CSS Grid FundamentalsTwo-dimensional layout with tracks, gaps, placement, fr units, and when grid beats flex for page scaffolding.
- Display Block Inline Flex GridHow display changes layout participation — block vs inline vs inline-block, and when flex/grid formatting contexts take over.