Flexbox vs Grid: A Decision Rule That Actually Works
One dimension or two — the rule for choosing between Flexbox and Grid, plus the modern Grid features that replace media queries entirely.
Table of contents
- Flexbox: content-driven
- Grid: layout-driven
- Named areas for page layout
- Modern features that remove media queries
- Both, usually
- Frequently asked questions
- Is Grid slower than Flexbox?
- Should I still use gap with Flexbox?
- Why does my flex item overflow its container?
- Do I need a CSS framework for layout?
- Related reading
- References
The rule: Flexbox for one dimension, Grid for two.
If you are arranging items along a single line — a row of buttons, a nav bar, an icon next to text — that is Flexbox. If you are placing items into rows and columns that align with each other, that is Grid.
Flexbox: content-driven#
Flexbox sizes items based on their content and distributes leftover space. That makes it right when you do not know or care how wide each item is.
.toolbar {
display: flex;
align-items: center;
gap: 0.75rem;
}
.toolbar .spacer {
margin-left: auto;
} /* push the rest right */The margin-left: auto trick is worth knowing — it absorbs all free space and is cleaner than wrapping groups in extra divs.
/* The classic sticky footer */
.page {
display: flex;
flex-direction: column;
min-height: 100dvh;
}
.page main {
flex: 1;
}Grid: layout-driven#
Grid defines the structure first, then places items into it. That makes it right when items must align across both axes.
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
gap: 1.25rem;
}Those two lines are a fully responsive card grid with no media queries. auto-fit fits as many columns as will hold a 16rem minimum, and 1fr shares the remainder equally. At 1400px you get four columns; at 400px you get one. Nothing to maintain.
The auto-fit versus auto-fill difference: auto-fit collapses empty tracks so three items stretch to fill the row; auto-fill keeps them, leaving a gap. auto-fit is what you want most of the time.
Named areas for page layout#
.layout {
display: grid;
grid-template-areas:
'header header'
'sidebar main'
'footer footer';
grid-template-columns: 16rem 1fr;
}
.layout > header {
grid-area: header;
}
.layout > aside {
grid-area: sidebar;
}
@media (width < 48rem) {
.layout {
grid-template-areas: 'header' 'main' 'sidebar' 'footer';
grid-template-columns: 1fr;
}
}The layout is legible from the CSS alone, and the mobile version reorders visually without touching the HTML. Note that this changes visual order only — DOM order still determines tab order, so keep the DOM in a sensible reading sequence.
Modern features that remove media queries#
Container queries — respond to the container's width, not the viewport's. This is what makes a component genuinely reusable:
.card-container {
container-type: inline-size;
}
@container (width > 30rem) {
.card {
grid-template-columns: 8rem 1fr;
}
}The same card is stacked in a narrow sidebar and horizontal in a wide main column, with no knowledge of the page layout.
Subgrid — a nested grid aligning to its parent's tracks, so card headers and footers line up across a row even with different content lengths.
min(), max(), clamp() — fluid sizing without breakpoints:
.container {
width: min(80rem, 100% - 2rem);
margin-inline: auto;
}
h1 {
font-size: clamp(2rem, 5vw, 3.5rem);
}Both, usually#
Real layouts nest them. Grid for the page and card structure; Flexbox inside each card for the row of metadata. The question is never which to adopt — it is which fits the specific box you are styling.
Frequently asked questions#
Is Grid slower than Flexbox?#
Not meaningfully. Both are highly optimised. Deeply nested layouts of either cost more than a flat one.
Should I still use gap with Flexbox?#
Yes — it has been supported everywhere for years and replaces the negative-margin hacks entirely.
Why does my flex item overflow its container?#
Flex items default to min-width: auto, which refuses to shrink below their content. Add min-width: 0 (or overflow: hidden) to allow shrinking. This is the single most common Flexbox bug.
Do I need a CSS framework for layout?#
No. grid-template-columns: repeat(auto-fit, minmax(...)) plus gap replaces most of what a grid framework provides, in two lines and with no class-name vocabulary to learn.
Related reading#
- CSS Custom Properties
- CSS Container Queries
- Tidy a stylesheet with the CSS Formatter.