Grid and Flexbox solve different problems — Grid lays out a page in two dimensions, Flexbox distributes items along one — and most real interfaces need both, not one over the other. The short version: reach for Grid when you're arranging a page or a region into rows and columns at once, reach for Flexbox when you're distributing items along a single row or column, and expect to nest one inside the other constantly. Teams doing professional web development treat this choice the same way — pick the layout primitive that matches the problem, not the one that's trendiest.
Grid lets you define rows and columns together and place items anywhere in that two-dimensional space in a single declaration. A parent becomes a grid, and its direct children fall into the cells that `grid-template-columns` and `grid-template-rows` define:
.page {
display: grid;
grid-template-columns: 240px 1fr;
grid-template-rows: auto 1fr auto;
gap: 24px;
}That one block replaces what used to take floats, negative margins, or a table — a sidebar, a main content area, and a footer, each sized independently on two axes at once. Grid is the only native CSS mechanism that reasons about rows and columns as a single structure rather than one axis at a time. See MDN's CSS Grid Layout reference for the full property list.
Flexbox distributes a set of items along a single axis — a row or a column, never both — and its whole vocabulary is built around that one axis: how items grow, shrink, and align relative to each other and to the container.
.toolbar {
display: flex;
justify-content: space-between;
align-items: center;
gap: 12px;
}Ask Flexbox to also control wrapping onto a second axis and it will wrap, but it treats each wrapped row as its own independent flex line — it does not align items across rows into a shared grid the way Grid does. That's not a bug; it's the model doing exactly what one-dimensional distribution means. See MDN's Flexible Box Layout reference for the full alignment vocabulary.
| Grid | Flexbox | |
|---|---|---|
| Dimension | Two axes at once (rows + columns) | One axis at a time (row or column) |
| Primary use case | Page and region-level layout | Distributing a group of items |
| Alignment model | Items placed into a defined grid of cells/areas | Items aligned and spaced along one line |
| Content-driven sizing | Tracks can size to content (auto, minmax()) | Items grow/shrink to fill the line (flex-grow/shrink) |
| Nesting behavior | A grid cell can itself be a flex container | A flex item can itself be a grid container |
Reach for Grid any time the problem is genuinely two-dimensional: a full page skeleton (header, sidebar, main, footer), a card gallery where every row needs equal-height cells regardless of content length, layouts where elements deliberately overlap, or a region complex enough that naming areas with grid-template-areas makes the intent legible at a glance. If you find yourself trying to keep two separate rows of items aligned into columns with Flexbox, that's the signal you actually need Grid.
Reach for Flexbox for anything that's fundamentally a single line of items: a navbar, a row of buttons, the fields in a form row, or centering one item inside its container. Flexbox's flex-grow and flex-shrink exist specifically for one-axis distribution problems — letting a search input expand to fill leftover space next to a fixed-width button, for instance — and Grid has no equivalent concept because it isn't solving a one-axis problem in the first place.
This is Flexbox's signature one-liner — no negative margins, no absolute positioning:
.center {
display: flex;
justify-content: center;
align-items: center;
}Grid's repeat() and minmax() produce a responsive card grid with no media query at all — columns are added or removed automatically as the container width changes:
.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
gap: 16px;
}A navbar is a one-dimensional row of items that needs to wrap and space itself out — Flexbox's native job:
.navbar {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
gap: 16px;
}Yes, and in practice this is the normal pattern, not an edge case. Grid handles the macro layout — the page skeleton, or the grid of cards — while Flexbox handles the micro-distribution inside each cell. A card grid is the clearest example: Grid lays out the gallery of cards with repeat(auto-fit, minmax(...)), and inside each individual card, Flexbox stacks the heading, body text, and a button with justify-content: space-between so the button always sits at the bottom regardless of how much text is above it. Neither layout model replaces the other; they compose.
Both specifications have been fully supported in every evergreen browser for years — there's no meaningful support gap left to design around, and @supports feature queries are unnecessary for standard Grid or Flexbox usage. The one genuinely newer addition is subgrid, which lets a nested grid inherit its parent's track sizing instead of defining its own — useful for aligning content across nested components, but an enhancement on top of the baseline model, not a prerequisite for using Grid at all.
No. They solve different problems — Grid handles two-dimensional layout, Flexbox handles one-dimensional distribution — and most real interfaces use both together rather than one in place of the other.
Yes, and this is the normal pattern: Grid for the page or gallery-level structure, Flexbox nested inside individual grid cells to distribute their contents.
Flexbox is usually easier to start with because it only has one axis to reason about. But both are needed quickly in practice — a simple page with a centered button and a card row already uses both.
Only partially, via wrapping. A wrapped Flexbox container creates multiple flex lines, but each line is sized and aligned independently — it does not create a shared grid of aligned rows and columns the way Grid does.
No. Bootstrap's grid is a 12-column layout built with Flexbox classes (or floats, in older versions) — it predates widespread native Grid support and is a different mechanism, not a wrapper around display: grid.
Both are fully supported across every evergreen browser with no meaningful gap. Support is not a factor in choosing between them anymore — the choice should be based purely on whether the problem is one-dimensional or two-dimensional.
Not meaningfully for typical layouts. Both are native browser layout engines, not JavaScript libraries, so there's no extra runtime cost beyond normal layout and paint — performance differences between the two are not a practical consideration when choosing which to use.