Articles › CSS & Web Design

CSS Flexbox vs Grid: A Practical Guide to Modern Layouts

Learn when to use Flexbox and when to use CSS Grid, with practical patterns for navbars, cards, holy-grail layouts, responsive grids and centering — without media query overload.

Flexbox and CSS Grid replaced a decade of float hacks and clearfixes. Together they can build virtually any layout with a few lines of CSS. The question developers ask most is which one should I use? This guide answers that with clear rules and copy-ready patterns.

The one-sentence difference

  • Flexbox is one-dimensional: it lays items out in a row or a column and distributes space along that line.
  • Grid is two-dimensional: it defines rows and columns at the same time and places items into that structure.

A practical heuristic: Flexbox is content-out (items decide their size, the container distributes leftovers); Grid is layout-in (the container defines tracks, items fill them).

Flexbox essentials

.toolbar {
  display: flex;
  flex-direction: row;          /* row | column */
  justify-content: space-between; /* main axis */
  align-items: center;          /* cross axis */
  gap: 12px;
  flex-wrap: wrap;
}

The two axes are the key concept:

Property Axis Common values
justify-content main axis flex-start, center, space-between, space-around
align-items cross axis stretch, center, flex-start, baseline
align-self cross axis (one item) same as align-items

The flex shorthand

Each child can grow, shrink and have a base size:

.item { flex: 1 1 200px; } /* grow, shrink, basis */
  • flex: 1 — share the remaining space equally.
  • flex: none — keep the natural size.
  • flex: 0 0 280px — a fixed-width sidebar.

Tip: If a flex item with long text refuses to shrink, add min-width: 0. Flex items default to min-width: auto, which prevents them from shrinking below their content.

Flexbox patterns

Navbar with a pushed-right action:

.nav { display: flex; align-items: center; gap: 16px; }
.nav__actions { margin-inline-start: auto; } /* pushes to the end — RTL-friendly */

Perfect centering:

.center { display: flex; justify-content: center; align-items: center; min-height: 100vh; }

Cards with buttons stuck to the bottom:

.card { display: flex; flex-direction: column; }
.card__footer { margin-top: auto; }

Grid essentials

.dashboard {
  display: grid;
  grid-template-columns: 240px 1fr;
  grid-template-rows: 64px 1fr auto;
  gap: 16px;
  min-height: 100vh;
}

The fr unit means "a fraction of the free space". 1fr 2fr gives the second column twice the space of the first.

Named template areas

Grid areas make complex layouts readable — the CSS literally draws the layout:

.page {
  display: grid;
  grid-template-columns: 260px 1fr;
  grid-template-areas:
    "header  header"
    "sidebar main"
    "footer  footer";
}

.header  { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main    { grid-area: main; }
.footer  { grid-area: footer; }

@media (max-width: 768px) {
  .page {
    grid-template-columns: 1fr;
    grid-template-areas: "header" "main" "sidebar" "footer";
  }
}

Changing the layout on mobile only requires redrawing the areas.

The responsive grid without media queries

This single line creates a card grid that adapts to any width:

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 20px;
}
  • minmax(260px, 1fr) — each column is at least 260px and can grow.
  • auto-fill — creates as many columns as fit.
  • auto-fit — like auto-fill, but collapses empty tracks so existing items stretch.

Spanning and placing items

.featured {
  grid-column: span 2;
  grid-row: span 2;
}

.full-width { grid-column: 1 / -1; } /* from first to last line */

This is how "bento" layouts with a large featured card are built.

Flexbox or Grid? A decision table

Situation Choose
Navbar, toolbar, button group Flexbox
Centering a single element Either (Grid: place-items: center)
Items of unknown size wrapping naturally (tags, chips) Flexbox
Card gallery with equal columns Grid
Whole-page layout (header/sidebar/main/footer) Grid
Aligning content inside a card Flexbox
Items that must line up in both rows and columns Grid

In real projects you combine them: Grid for the page and card gallery, Flexbox inside each card and for the navbar.

Writing layouts that work in RTL

Persian, Arabic and Hebrew sites are right-to-left. Use logical properties and your layout flips automatically when dir="rtl":

Physical Logical
margin-left margin-inline-start
padding-right padding-inline-end
left: 0 inset-inline-start: 0
border-left border-inline-start
text-align: left text-align: start

Flexbox and Grid already follow the writing direction: justify-content: flex-start means "right" in RTL. Avoid row-reverse hacks for RTL — logical properties are cleaner.

Subgrid and container queries

Two newer features are now supported in all modern browsers:

Subgrid lets nested elements align to the parent grid — perfect for cards whose titles, text and buttons should line up across a row:

.cards { display: grid; grid-template-columns: repeat(3, 1fr); }
.card {
  display: grid;
  grid-row: span 3;
  grid-template-rows: subgrid;
}

Container queries let a component adapt to its container's width instead of the viewport:

.card-wrapper { container-type: inline-size; }

@container (min-width: 420px) {
  .card { display: grid; grid-template-columns: 140px 1fr; }
}

Common mistakes

  1. Using width: 33.33% with margins instead of gap.
  2. Forgetting min-width: 0 on flex items with long text or code.
  3. Building page layouts with nested flex rows instead of a grid.
  4. Using physical properties (left, margin-right) in bilingual sites.
  5. Too many breakpoints — auto-fill + minmax often removes the need for them.

Summary

Use Flexbox to align and distribute items along a line, and Grid to define two-dimensional structures. Combine them freely, rely on gap, fr, minmax and named areas, and write logical properties so your layouts work in both LTR and RTL. With these tools you'll rarely need a CSS framework for layout.

FAQ

Is Grid slower than Flexbox?

No meaningful difference in real-world pages. Choose based on the layout problem, not performance.

Should I still use a framework like Bootstrap for grids?

Not for layout alone. Native Grid is more powerful and needs less markup. Frameworks still help with design systems and components.

Can Flexbox replace Grid?

For simple rows, yes. But two-dimensional layouts built with Flexbox need extra wrappers and fragile widths — Grid solves them directly.