Flexbox vs Grid
Flexbox vs Grid in CSS: one-dimensional flow vs two-dimensional layout, and how to tell which a design needs.
Last updated
The short answer
Flexbox lays out items along one axis — a row of buttons, a nav bar, centering something — letting content size drive the layout. Grid lays out two axes at once — a page skeleton, a card gallery — for when you want to define rows and columns first and place content into them.
| Dimension | Flexbox | Grid |
|---|---|---|
| Dimensions | One axis at a time (row or column) | Two axes at once (rows and columns) |
| Sizing driven by | Content size, by default | Explicit track definitions |
| Item placement | Flows in source order | Can place items anywhere, out of order |
| Overlap | Not really possible | Items can overlap by design |
| Typical use | Nav bars, button groups, centering | Page layouts, card grids, dashboards |
Choose Flexbox when
- →You're arranging items in a single row or column — a toolbar, a nav menu, a list of tags that should wrap.
- →You want content's natural size to drive the layout, with flex-grow/shrink handling the leftover space.
- →You need to center something vertically and horizontally without a hack — Flexbox does this natively.
Choose Grid when
- →You're laying out a page skeleton — header, sidebar, main content, footer — as rows and columns at once.
- →You want to define the structure explicitly (grid-template-columns/rows) and place items into named areas.
- →Items need to span multiple rows or columns, or overlap — things Flexbox has no clean way to express.
The catch nobody mentions
They aren't competing for the same job as often as the framing suggests — you can nest Flexbox inside Grid (and vice versa), and most non-trivial layouts do exactly that: Grid for the page's overall structure, Flexbox for aligning items within each grid cell. Treating this as an either/or choice for an entire layout usually means picking the wrong tool for at least one part of it.
Common mistakes
display: flex; flex-wrap: wrap;Wrapping flex items produces rows that do not align into columns, because each row sizes independently. If the result should be a grid, using one avoids fighting the layout with fixed widths.
display: grid; grid-template-columns: repeat(3, 1fr);A fixed column count does not respond to the viewport, so the same three columns are cramped on a phone. auto-fit with minmax lets the count follow the available width without a media query.
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));display: grid; place-content: center;Centres the tracks within the container rather than the items within their cells, which looks identical until the container is larger than the content. place-items is what centres the children.
Questions
Is there a simple rule for choosing?
One dimension is flex, two are grid. A row of buttons or a navigation bar is flex; a card layout aligning in both directions is grid. Content-driven sizing favours flex, layout-driven favours grid.
Can I nest them?
Yes, and it is the usual arrangement — grid for the page structure, flex inside each cell for its contents. They are complementary rather than competing, which the framing of the comparison tends to obscure.
How do I build a responsive card layout without media queries?
repeat(auto-fit, minmax(240px, 1fr)) fits as many columns as the width allows and stretches them to fill. It is the single most useful thing grid does that flex cannot express.
Which is better supported?
Both, comprehensively, in every browser anyone still targets. Grid arrived later so the doubt persists longer than the facts justify — subgrid is the only part still worth checking.
What about gap?
It works in both now, including flex, which removes the old negative-margin workarounds entirely. If you learned flex before 2021, gap is the change most worth revisiting.