CSS Grid vs Flexbox — Stop Asking Which Is Better

webdev css grid flexbox layout

r/css will argue Grid vs Flex forever. Shipping teams pick both before lunch. The useful question is not “which is better?” — it is “am I arranging in two dimensions or one?”

The one-sentence split

  • Grid — control rows and columns as a single system (page regions, galleries, aligned form labels)
  • Flexbox — distribute items along a single axis (nav links, tag chips, card actions)

Try page structures in a CSS grid playground when regions are the hard part; use Flex when children just need to space along a line.

Decision table

ProblemPreferWhy
Header / main / sidebar / footerGridNamed areas stay sane
Equal-height card mosaicGridauto-fit + minmax
Navbar links with space-betweenFlexOne axis
Center icon + labelFlexalign-items: center
Magazine-style asymmetric layoutGridLine-based placement
Unknown number of wrapping chipsFlexflex-wrap
Align columns across rows (forms)GridShared tracks

Page shell with Grid

.page {
  min-height: 100dvh;
  display: grid;
  grid-template-columns: 240px 1fr;
  grid-template-rows: auto 1fr auto;
  grid-template-areas:
    "side header"
    "side main"
    "side footer";
}
@media (max-width: 800px) {
  .page {
    grid-template-columns: 1fr;
    grid-template-areas: "header" "main" "footer";
  }
  .side { display: none; }
}

That structure fights you in pure Flex — you nest wrappers until it accidentally becomes a grid.

Component guts with Flex + nesting

.card-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  justify-content: flex-end;
  align-items: center;
}
.dashboard {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: 1rem;
}
.widget {
  grid-column: span 4;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

Grid places the widget; Flex owns the header chrome. Normal, not impure.

Myths and debugging

MythReality
“Grid replaces Flex”Nest freely
“Flex for whole pages always”Gets awkward for 2D
gap in flex is unreliable”Widely supported now

In DevTools, Grid overlay shows tracks; Flex overlay shows main/cross axis. Mysterious stretch is often Flex’s default align-items: stretch, not bad content height. Migrating a Flex shell to Grid? Move one region at a time so you can bisect regressions.

Litmus test: if one item grows taller, should neighbors in the other dimension realign as a system? Yes → Grid. No → Flex. Stop asking which is better; ask which axis you are designing.

Auto-fit galleries and form alignment

Card galleries are a Grid highlight:

.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: 1rem;
}

Forms that must align labels and inputs across rows also want Grid (or a shared column template), not nested Flex rows that drift as copy lengths change. Conversely, a toolbar of actions that reflows onto two lines is Flex with flex-wrap — Grid is overkill when there is no second axis to align.

Subgrid note

When child grids must align to a parent’s columns, subgrid (where supported) beats brittle percentage hacks. Feature-detect or progressive-enhance; do not rewrite the whole site on subgrid alone. For most dashboards, nested Grid + Flex as described above is enough without waiting on subgrid.

When a teammate insists “we only use Flex here,” ask them to sketch the alignment lines on paper. If they draw both rows and columns, you have already won the Grid argument — the rest is syntax.

Container queries

As container queries spread, component-level Grid and Flex choices can respond to parent width instead of only viewport media queries — layout systems get more local and less global, which reduces breakpoint spaghetti.