Skip to content
All posts
Tutorial4 min read

CSS Grid vs Flexbox — When to Use Each (With Real Examples)

DebuggerMe TeamDebuggerMe TeamApril 19, 2026
Clean web design layout on a computer screen
Photo by Unsplash
On this page

Every few months this debate resurfaces. The answer hasn't changed: use both, for different things.

Grid and Flexbox are complementary tools. Knowing when to reach for each is a fundamental CSS skill.

The One-Line Rule

  • Flexbox = one-dimensional layout (a row or a column)
  • Grid = two-dimensional layout (rows and columns simultaneously)

Everything flows from this.

Flexbox: What It's Great At

css
.nav {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
}

A nav is a single row of items with space between them. That's Flexbox's home turf.

Centering a single element

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

The most common use case in all of CSS. Grid works too, but Flexbox is more expressive here.

Card content layout

Inside a card, you want the title and body to grow, and the button to pin to the bottom:

css
.card {
    display: flex;
    flex-direction: column;
}
.card-body {
    flex: 1; /* grows to fill available space */
}
.card-button {
    margin-top: auto; /* pins to bottom */
}

[!TIP] margin-top: auto in a flex column is the cleanest way to push an element to the bottom of its container. No absolute positioning needed.

Grid: What It's Great At

Page-level layouts

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

This creates a complete app layout — sidebar, header, main content, footer — in 8 lines. Try doing that with Flexbox.

Card grids that adapt to content

css
.grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: 1.5rem;
}

auto-fill + minmax = a responsive grid with no media queries. Cards reflow automatically as the viewport shrinks.

Overlapping elements

Grid allows you to place multiple items in the same cell:

css
.hero {
    display: grid;
}
.hero-image,
.hero-text {
    grid-column: 1;
    grid-row: 1;
}

Both elements occupy the same space. The text overlays the image. This is awkward with Flexbox and impossible without position: absolute.

The "Which One?" Decision Tree

code
Does the layout have both rows AND columns?
├── YES → Grid
└── NO (just one axis)
    ├── Is it a single item to be centered?
    │   └── Either works, Flexbox is simpler
    ├── Do children need to wrap to new lines?
    │   ├── YES and they need to align across rows? → Grid
    │   └── YES but rows are independent? → Flexbox with wrap
    └── Is it a simple row/column of items? → Flexbox

Common Mistakes

Mistake 1: Using Flexbox for a card grid

css
/* ❌ Don't do this */
.cards {
    display: flex;
    flex-wrap: wrap;
    gap: 1rem;
}
.card {
    flex: 0 0 calc(33.333% - 1rem);
}

This breaks at different viewport sizes and requires math to handle gaps. Use Grid instead:

css
/* ✅ Do this */
.cards {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: 1rem;
}

Mistake 2: Using Grid for simple alignment

css
/* ❌ Overkill */
.header {
    display: grid;
    grid-template-columns: auto 1fr auto;
    align-items: center;
}

/* ✅ Clear intent */
.header {
    display: flex;
    align-items: center;
    gap: 1rem;
}

Mistake 3: Forgetting you can nest them

The real power is combining both:

css
/* Outer structure: Grid */
.layout {
    display: grid;
    grid-template-columns: 240px 1fr;
}

/* Inner content: Flexbox */
.sidebar {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

Use Grid for the page-level skeleton. Use Flexbox inside each section.

Modern CSS That Changes Things

In 2026, container queries change the equation slightly:

css
.card-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(280px, 100%), 1fr));
}

@container (min-width: 600px) {
    .card {
        grid-template-columns: auto 1fr;
    }
}

But the fundamental rule still holds: Grid for 2D structure, Flexbox for 1D alignment.

Quick Reference

Use CaseWinner
Navbar with logo + links + buttonFlexbox
Responsive card gridGrid
Centering a modalEither (Flexbox is simpler)
Full-page app layoutGrid
Card with pinned footer buttonFlexbox
Overlapping hero text on imageGrid
Form with label + input pairsGrid
Tag/badge list that wrapsFlexbox
Dashboard with sidebar + mainGrid
Button with icon + textFlexbox
DebuggerMe Team

Written by

DebuggerMe Team

The DebuggerMe team builds developer tools, writes technical content, and helps teams ship better software.

Share this post

Back to all posts

Related Articles

All articles →