CSSBeginner

CSS Flexbox vs Grid: When to Use Which

Flexbox and Grid both lay out elements, but they think differently. Learn the one-dimension vs two-dimension rule and build real layouts with each.

Flexbox boxes in a single row next to a grid of boxes spanning rows and columns
On this page

Flexbox and CSS Grid are the two modern layout systems in CSS, and beginners often ask which one is "better". The honest answer is neither. They solve different problems, and professional layouts use both, often on the same page.

The one rule to remember#

Flexbox lays things out in one dimension: a row or a column.

Grid lays things out in two dimensions: rows and columns at the same time.

Another way to put it: Flexbox is content-first. Items decide how much space they need, and the container distributes what's left. Grid is layout-first. You define the tracks, then place items into them.

display: flexdisplay: grid one axis: a row or a columntwo axes: rows and columns
Flexbox distributes items along a single axis; Grid aligns them on rows and columns at once

Flexbox basics#

Turn any element into a flex container with display: flex. Its direct children become flex items arranged in a row:

CSS
.toolbar {
  display: flex;
  align-items: center;            /* alignment on the cross axis */
  justify-content: space-between; /* distribution on the main axis */
  gap: 12px;
}

The properties you'll use 90% of the time:

Property What it does
flex-direction row (default) or column
justify-content Distributes space along the main axis
align-items Aligns items on the cross axis
gap Adds space between items
flex-wrap Lets items wrap onto new lines
flex: 1 (on an item) Makes the item grow to fill available space

Example: a navigation bar#

HTML
<nav class="navbar">
  <a class="logo" href="/">Brand</a>
  <ul class="links">
    <li><a href="/docs">Docs</a></li>
    <li><a href="/blog">Blog</a></li>
  </ul>
  <a class="button" href="/signup">Sign up</a>
</nav>
CSS
.navbar {
  display: flex;
  align-items: center;
  gap: 24px;
}

.links {
  display: flex;
  gap: 16px;
  margin: 0 auto 0 0;   /* the auto right margin pushes the button to the far right */
  padding: 0;
  list-style: none;
}

The auto-margin trick

In a flex container, margin-left: auto or margin-right: auto on an item absorbs all the free space on that side. It's the cleanest way to push one item away from the others.

Example: perfect centring#

The famous "how do I centre a div?" question has a short answer with Flexbox:

CSS
.center {
  display: flex;
  justify-content: center;
  align-items: center;
}

With Grid, display: grid; place-items: center; does the same thing.

Grid basics#

Grid shines when you need items aligned in both directions. Define columns (and optionally rows) on the container:

CSS
.gallery {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
}

The fr unit means "one fraction of the free space", so repeat(3, 1fr) creates three equal columns.

Example: a responsive card grid with no media queries#

This one line is worth memorising:

CSS
.cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: 24px;
}

It says "fit as many columns as you can, each at least 250px wide, and stretch them to fill the row." On a phone you get one column; on a wide monitor you might get four, all without a single media query.

Example: a full page layout#

Grid's grid-template-areas lets you draw your layout as text:

CSS
.page {
  display: grid;
  grid-template-columns: 240px 1fr;
  grid-template-rows: auto 1fr auto;
  grid-template-areas:
    "header  header"
    "sidebar main"
    "footer  footer";
  min-height: 100vh;
}

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

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

Notice how the mobile version simply rearranges the areas. The HTML doesn't change at all.

Side-by-side comparison#

Flexbox Grid
Dimensions One (row or column) Two (rows and columns)
Approach Content-first Layout-first
Best for Navbars, toolbars, button groups, centring Page layouts, galleries, dashboards, forms
Sizing Items size themselves, then flex Tracks define sizes, items fill them
Overlapping items Awkward Easy: place items in the same cell

Using them together#

Real interfaces nest the two. A typical pattern is Grid for the overall structure, Flexbox inside each component:

CSS
/* Grid arranges the cards */
.cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: 24px;
}

/* Flexbox arranges the content inside each card */
.card {
  display: flex;
  flex-direction: column;
}

.card .footer {
  margin-top: auto;   /* pins the footer to the bottom of every card */
}

Grid stretches every card in a row to the same height, and the margin-top: auto trick keeps the footers aligned even when the cards contain different amounts of text. It's a small detail that makes designs look polished.

Quick decision guide#

Ask yourself:

  1. Am I arranging items in a single line? Use Flexbox.
  2. Do I need items to line up in rows and columns? Use Grid.
  3. Should the content decide the size? Use Flexbox.
  4. Should the layout decide the size? Use Grid.

When in doubt, start with Flexbox for small components and Grid for anything that looks like a table, a gallery or a page skeleton.

Recap#

  • Flexbox is one-dimensional and content-first, which makes it perfect for components.
  • Grid is two-dimensional and layout-first, which makes it perfect for page structure and galleries.
  • repeat(auto-fill, minmax(…, 1fr)) gives you responsive grids without media queries.
  • Combine them: Grid for the structure, Flexbox inside the pieces.

Open your browser's DevTools on any modern website and inspect the layout. You'll find both systems working together everywhere.