CSS Grid vs Flexbox: When to Use Each One
A practical guide to choosing between CSS Grid and Flexbox — with clear rules for when each layout system is the right tool and real examples of common UI patterns.
The "Grid vs Flexbox" debate misses the point. They're not competing tools — they solve different problems. Understanding which to reach for in any situation makes your CSS cleaner, more maintainable, and easier to reason about.
The One-Line Rule
Flexbox = one-dimensional layout (a row OR a column) Grid = two-dimensional layout (rows AND columns simultaneously)
If you're arranging items in a single line — a navigation bar, a button group, a card's content area — that's Flexbox. If you're creating a page layout with rows and columns that need to align — a product grid, a dashboard, a magazine layout — that's Grid.
Flexbox: The Right Tool for Components
Flexbox shines inside components where you're arranging a single flow of items.
Navigation Bar
/* Perfect Flexbox use case: items in a row with space between */
.navbar {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 24px;
height: 60px;
}
.navbar-links {
display: flex;
align-items: center;
gap: 24px;
list-style: none;
}Card Component Internal Layout
.card {
display: flex;
flex-direction: column;
}
.card-content {
flex: 1; /* Takes remaining space, pushing footer to bottom */
padding: 16px;
}
.card-footer {
padding: 16px;
border-top: 1px solid #eee;
}This "push footer to bottom" pattern is classic Flexbox. Grid would be cumbersome here.
Centering
/* Centering a single element — Flexbox is simplest */
.container {
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
}Button Group
.button-group {
display: flex;
gap: 8px;
flex-wrap: wrap; /* Wraps on small screens */
}Grid: The Right Tool for Layouts
Grid is the right choice when items need to align across both rows and columns simultaneously.
Page Layout
/* Classic page layout that would be painful with Flexbox */
.page {
display: grid;
grid-template-columns: 250px 1fr;
grid-template-rows: 60px 1fr auto;
grid-template-areas:
"sidebar header"
"sidebar main"
"sidebar footer";
min-height: 100vh;
}
.sidebar { grid-area: sidebar; }
.header { grid-area: header; }
.main { grid-area: main; }
.footer { grid-area: footer; }Responsive Product Grid
/* Auto-fill columns — items wrap automatically based on min/max */
.product-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 24px;
}This single rule creates a fully responsive grid — no media queries needed. 3 columns on desktop, 2 on tablet, 1 on mobile. This is impossible to replicate cleanly with Flexbox.
Dashboard with Mixed Sizes
.dashboard {
display: grid;
grid-template-columns: repeat(12, 1fr);
gap: 16px;
}
/* Wide card spans 8 columns, narrow spans 4 */
.stats-overview { grid-column: span 8; }
.recent-activity { grid-column: span 4; }
/* Full-width chart below */
.main-chart { grid-column: 1 / -1; }
@media (max-width: 768px) {
.stats-overview,
.recent-activity,
.main-chart { grid-column: 1 / -1; }
}Holy Grail Layout
body {
display: grid;
grid-template-columns: 200px 1fr 200px;
grid-template-rows: auto 1fr auto;
min-height: 100vh;
}
header { grid-column: 1 / -1; }
.left-sidebar { grid-column: 1; }
main { grid-column: 2; }
.right-sidebar { grid-column: 3; }
footer { grid-column: 1 / -1; }They Work Together
The best layouts often use both. Grid for the macro layout, Flexbox for component internals:
/* Grid handles the page structure */
.app {
display: grid;
grid-template-columns: 280px 1fr;
grid-template-rows: 64px 1fr;
}
/* Flexbox handles the header's internal arrangement */
.header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 24px;
}
/* Grid handles the card grid */
.post-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
gap: 24px;
padding: 24px;
}
/* Flexbox handles each card's internal layout */
.post-card {
display: flex;
flex-direction: column;
}
.post-card-content {
flex: 1;
}Common Mistakes
1. Using Flexbox to create a card grid. The famous flex-wrap card grid where the last row has misaligned items of different widths:
/* BAD: Last row looks wrong if fewer than 3 items */
.cards {
display: flex;
flex-wrap: wrap;
gap: 16px;
}
.card {
flex: 1 1 300px; /* Items in last row stretch to fill */
}
/* GOOD: Grid handles this correctly */
.cards {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 16px;
}2. Using Grid for a simple button row.
/* Overkill */
.actions {
display: grid;
grid-auto-flow: column;
gap: 8px;
}
/* Right tool */
.actions {
display: flex;
gap: 8px;
}3. Forgetting gap exists. Still seeing margin-right on all-but-last-child. Use gap — it works in both Flexbox and Grid and doesn't add margin to the last item.
4. Not using fr units. The fractional unit in Grid is one of its killer features:
/* Three equal columns */
grid-template-columns: 1fr 1fr 1fr;
/* Sidebar + main content with 3:1 ratio */
grid-template-columns: 1fr 3fr;Quick Decision Guide
| Use Flexbox when... | Use Grid when... |
|---|---|
| Content in a single row or column | Layout needs rows AND columns |
| Items have variable/unknown size | Items need to align across rows |
| Navigation, button groups, form rows | Page layout, card grids, dashboards |
| Content dictates layout | Layout dictates content placement |
Key Takeaways
- Flexbox is for one-dimensional layouts; Grid is for two-dimensional layouts
- Use Grid for page structure, Flexbox for component internals — they complement each other
repeat(auto-fill, minmax(Xpx, 1fr))is the best responsive grid pattern — no media queries neededgapworks in both Flexbox and Grid — stop using margin hacks for spacing between items- Card grids belong in CSS Grid, not Flexbox, to avoid alignment issues in the last row

Written by
Sabir KhaloufiFull-stack developer and tech blogger sharing in-depth tutorials on React, Next.js, AI, and modern web development.