CSS Grid vs Flexbox: When to Use Each

You need three cards in a row. Flexbox does that in four lines. Then the client wants a fourth card, and now you’re fighting flex-wrap, and the last row has one lonely card stretched across the full width because Flexbox has no idea it’s supposed to line up under the row above it.

This is usually the exact moment someone reaches for Grid. And it’s usually the moment they realize nobody ever explained when to reach for which — just a wall of syntax for both. Here’s the version that actually answers that.

Flexbox lays things out in one direction at a time — a row, or a column. Grid lays things out in two directions at once. If you’re aligning items along a single line, use Flexbox. If you’re building a layout where rows and columns need to line up with each other, use Grid. Most real pages use both, at different levels.

The one-sentence mental model

Flexbox is one-dimensional. Grid is two-dimensional.

That’s it — everything else follows from that. Flexbox items flow along a single axis and wrap onto a new line when they run out of room, but each line doesn’t know or care what the line before it looked like. Grid defines the rows and columns up front, so every item is placed into a specific track, and everything lines up — horizontally and vertically — on purpose.

That’s exactly what broke in the four-card example above: row two had no relationship to row one, because Flexbox was never tracking rows in the first place.

Grid vs Flexbox at a glance

FlexboxGrid
DimensionsOne axis at a time (row or column)Two axes at once (rows and columns)
Best forAligning items inside a componentStructuring the page or section layout
Driven byContent — items size themselvesLayout — you define the tracks, content fills them
WrappingNew rows have no memory of the row beforeItems are placed into a fixed grid; rows and columns stay aligned
Typical useNavbar, button group, form row, centering one itemPage shell, image gallery, card grid, dashboard
Browser supportUniversal, no prefixes neededUniversal, no prefixes needed

When Flexbox is the right call

Reach for Flexbox when you’re aligning a handful of items along one line and want them to size themselves based on content:

That’s a navbar: logo on the left, links on the right, everything vertically centered, done. No grid tracks to define, no wasted setup for something this small.

Other jobs Flexbox is genuinely the better tool for:

  • Centering a single item vertically and horizontally
  • A row of buttons or tags that should wrap naturally when space runs out
  • Distributing space between a fixed number of items with space-between
  • Form rows where a label and input sit side by side
  • The inside of a card — image, title, description, button pinned to the bottom with margin-top: auto

When Grid is the right call

Reach for Grid when the layout itself has structure — actual rows and columns that need to relate to each other:

That’s a sidebar layout defined in four lines, with named areas instead of nth-child guesswork. Try building that with Flexbox and you’ll end up faking columns with fixed widths and margins — it’ll work, but you’re fighting the tool.

Grid is the better tool for:

  • Page-level layout: header, sidebar, main content, footer
  • Card grids where every card should line up in equal-height rows and columns
  • Image galleries with a fixed-track or masonry-style layout
  • Dashboards with panels of different sizes sharing the same underlying grid
  • Anything where you’d otherwise need nth-child selectors to fake column alignment

For equal-width cards that reflow automatically without a single media query, this is the pattern to know:

auto-fit and minmax() together mean the browser works out how many columns fit at the current width — no breakpoints to maintain.

You don’t have to pick one

This is the part that gets skipped in most explainers: production layouts almost always use both, at different levels.

Grid defines the macro structure — the page shell, the card grid, the overall skeleton. Flexbox handles the micro alignment inside each of those grid cells — the contents of a single card, the row of icons in a footer column. Neither tool replaces the other; they solve different-sized problems in the same layout.

If you’re nesting a grid inside a grid and want the inner grid’s tracks to actually line up with the outer one — useful when a card’s image, title and button need to align across cards even if descriptions run different lengths — subgrid is the tool for that. It reached Baseline widely-available status across browsers in March 2026, so it’s now safe to use in production without a fallback.

The decision checklist

flexboxAligning items along one row or column
gridBuilding the page skeleton — header, nav, main, aside, footer
flexboxContent of unknown length that should wrap naturally, like tags or chips
gridRows and columns need to visually line up with each other
flexboxLaying out what’s inside a single grid cell or card

Common mistakes

Using Flexbox for a full page layout

It basically works until the content doesn’t cooperate — then you’re adding wrapper divs and fixed widths to fake what Grid does natively.

Using Grid for a simple row of three buttons

It works, but it’s more setup than the problem needs. If you’re only ever thinking about one direction, you don’t need two-dimensional tooling.

Expecting flex-wrap to keep columns aligned

It won’t — that’s the four-card problem from the top of this post. Wrapped Flexbox rows have no relationship to each other. If alignment across rows matters, that’s your signal to switch to Grid.

Forgetting gap works on both

You don’t need margin hacks on either one anymore — gap handles spacing between items in Flexbox and between tracks in Grid, without adding extra space around the outer edge the way margins can.

Build the Flexbox part without doing the math by hand