CSS Grid vs Flexbox: When to Use Which
Two of the most powerful CSS layout systems—CSS Grid and Flexbox—have revolutionized how we build web layouts. Yet developers often struggle to decide when to use which. Should you use Grid for everything? Is Flexbox obsolete? The answer is neither: both tools excel at different tasks, and understanding when to reach for each will make you a more effective frontend developer.
In this comprehensive guide, we'll explore the fundamental differences between Grid and Flexbox, examine real-world use cases for each, and show you how to combine them for powerful, responsive layouts.
Flexbox is for one-dimensional layouts (row OR column). CSS Grid is for two-dimensional layouts (rows AND columns). But the best layouts often use both together!
Understanding the Core Difference
The fundamental difference lies in dimensionality. Flexbox works along a single axis (either horizontally or vertically), while Grid works with both axes simultaneously. Let's visualize this:
Flexbox arranges items along one axis; Grid controls both rows and columns simultaneously
Side-by-Side Comparison
Flexbox
- One-dimensional layout
- Content-first approach
- Items flow naturally
- Great for components
- Flexible item sizing
- Perfect for alignment
CSS Grid
- Two-dimensional layout
- Layout-first approach
- Explicit placement
- Great for page layouts
- Fixed track sizing
- Perfect for complex layouts
Flexbox Deep Dive
Flexbox (Flexible Box Layout) was designed to provide efficient alignment and distribution of space among items in a container, even when their sizes are unknown or dynamic. It excels at component-level layouts.
Basic Flexbox Setup
.flex-container {
display: flex;
/* Main axis direction */
flex-direction: row; /* row | row-reverse | column | column-reverse */
/* Wrapping behavior */
flex-wrap: wrap; /* nowrap | wrap | wrap-reverse */
/* Main axis alignment */
justify-content: center; /* flex-start | flex-end | center | space-between | space-around | space-evenly */
/* Cross axis alignment */
align-items: center; /* stretch | flex-start | flex-end | center | baseline */
/* Multi-line alignment */
align-content: stretch; /* flex-start | flex-end | center | space-between | space-around | stretch */
/* Gap between items */
gap: 16px;
}
.flex-item {
/* Growth factor */
flex-grow: 1; /* How much item should grow relative to others */
/* Shrink factor */
flex-shrink: 0; /* How much item should shrink relative to others */
/* Base size */
flex-basis: 200px; /* Initial size before growing/shrinking */
/* Shorthand: grow shrink basis */
flex: 1 0 200px;
/* Individual alignment override */
align-self: flex-end;
}
Flexbox Visual Guide
Flexbox alignment properties visualized
Flexbox Use Cases
Navigation Bars
Horizontal menus with flexible spacing between items
Card Components
Vertically stacked content with consistent alignment
Media Objects
Image with text content side-by-side
Equal Height Columns
Columns that stretch to match tallest sibling
Use Flexbox when you need to distribute space between items along a single axis, center content vertically/horizontally, or create components where items should grow/shrink dynamically based on available space.
CSS Grid Deep Dive
CSS Grid is designed for two-dimensional layouts, allowing you to define both rows and columns simultaneously. It's ideal for page-level layouts and complex component structures where you need precise control over positioning.
Basic Grid Setup
.grid-container {
display: grid;
/* Define columns */
grid-template-columns: 200px 1fr 200px; /* Fixed, flexible, fixed */
grid-template-columns: repeat(3, 1fr); /* Three equal columns */
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); /* Responsive! */
/* Define rows */
grid-template-rows: auto 1fr auto; /* Header, content, footer */
/* Gap between cells */
gap: 20px; /* row-gap and column-gap */
/* Named template areas */
grid-template-areas:
"header header header"
"sidebar main aside"
"footer footer footer";
}
.grid-item {
/* Span multiple columns */
grid-column: 1 / 3; /* Start at line 1, end at line 3 */
grid-column: span 2; /* Span 2 columns from current position */
/* Span multiple rows */
grid-row: 1 / 4; /* Start at line 1, end at line 4 */
/* Place in named area */
grid-area: header;
/* Self alignment within cell */
justify-self: center; /* Horizontal alignment */
align-self: center; /* Vertical alignment */
}
Grid Template Areas
One of Grid's most powerful features is the ability to define layouts using named areas. This makes your CSS incredibly readable and easy to modify.
Classic "Holy Grail" layout using grid-template-areas
.holy-grail {
display: grid;
min-height: 100vh;
gap: 16px;
grid-template-columns: 200px 1fr 200px;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"header header header"
"sidebar main aside"
"footer footer footer";
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
.aside { grid-area: aside; }
.footer { grid-area: footer; }
/* Responsive: Stack on mobile */
@media (max-width: 768px) {
.holy-grail {
grid-template-columns: 1fr;
grid-template-areas:
"header"
"main"
"sidebar"
"aside"
"footer";
}
}
Auto-Fit and Minmax: Responsive Without Media Queries
One of Grid's superpowers is creating responsive layouts without any media queries using auto-fit and minmax().
.card-grid {
display: grid;
/* Magic responsive formula */
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 24px;
padding: 24px;
}
/*
This creates a grid where:
- Each card is minimum 280px wide
- Cards grow equally to fill available space (1fr)
- Grid automatically adjusts number of columns
- No media queries needed!
On a 1200px screen: 4 columns
On a 900px screen: 3 columns
On a 600px screen: 2 columns
On a 400px screen: 1 column
*/
Grid Use Cases
Page Layouts
Complex layouts with headers, sidebars, and footers
Image Galleries
Pinterest-style layouts with varied sizes
Data Tables
Aligned columns with consistent widths
Dashboard Layouts
Widgets of different sizes in a grid
Decision Guide: Grid or Flexbox?
Not sure which to use? Follow this decision tree:
Using Grid and Flexbox Together
Here's the secret: you don't have to choose! The best layouts often combine both. Use Grid for the overall page structure and Flexbox for components within grid cells.
Page layout with Grid, components inside with Flexbox
/* Page layout with Grid */
.page {
display: grid;
min-height: 100vh;
grid-template-columns: 250px 1fr;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
}
/* Navigation with Flexbox */
.header {
grid-area: header;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 24px;
}
.nav-links {
display: flex;
gap: 24px;
}
/* Card grid inside main area */
.main {
grid-area: main;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 24px;
padding: 24px;
}
/* Card content with Flexbox */
.card {
display: flex;
flex-direction: column;
gap: 16px;
padding: 20px;
background: var(--bg-secondary);
border-radius: 12px;
}
.card-header {
display: flex;
align-items: center;
gap: 12px;
}
.card-footer {
display: flex;
justify-content: space-between;
margin-top: auto; /* Push to bottom */
}
Common Patterns
Centering Content (The Classic Problem)
.center-flexbox {
display: flex;
justify-content: center; /* Horizontal */
align-items: center; /* Vertical */
min-height: 100vh;
}
.center-grid {
display: grid;
place-items: center; /* Both axes at once! */
min-height: 100vh;
}
/* Or */
.center-grid-alt {
display: grid;
place-content: center;
}
Sticky Footer
.page-wrapper {
display: grid;
grid-template-rows: auto 1fr auto;
min-height: 100vh;
}
.header { /* auto height */ }
.main { /* takes remaining space (1fr) */ }
.footer { /* auto height, always at bottom */ }
Equal-Height Cards in a Row
.card-row {
display: flex;
gap: 24px;
}
.card {
flex: 1; /* Equal width */
display: flex;
flex-direction: column;
}
.card-body {
flex: 1; /* Fills remaining space */
}
.card-footer {
margin-top: auto; /* Always at bottom */
}
Quick Reference Cheat Sheet
| Use Case | Recommended | Why |
|---|---|---|
| Page layout (header, sidebar, main, footer) | Grid | Two-dimensional control needed |
| Navigation bar | Flexbox | Single row, flexible spacing |
| Card grid that wraps | Grid | auto-fit keeps alignment |
| Centering a single element | Grid | place-items: center is simplest |
| Items with varying sizes in a row | Flexbox | Content-based sizing |
| Form layout with labels/inputs | Grid | Aligned columns |
| Vertical stack with spacing | Flexbox | Simple, single axis |
| Pinterest-style masonry | Grid | grid-auto-rows with varying heights |
- Using Grid for everything: Not every layout needs two dimensions. Simple rows work better with Flexbox.
- Forgetting gap: Both Grid and Flexbox support `gap`. Use it instead of margins!
- Not using minmax(): For responsive grids, `minmax(250px, 1fr)` is your best friend.
- Over-nesting: You don't need a flex container inside a flex container inside a grid. Keep it simple.
Conclusion
CSS Grid and Flexbox aren't competitors—they're complementary tools that solve different problems. Understanding when to use each (and when to combine them) will dramatically improve your CSS skills.
Key Takeaways
- Flexbox = One-dimensional, content-driven, perfect for components
- Grid = Two-dimensional, layout-driven, perfect for page structure
- Use Grid for the layout, Flexbox for the components inside
- Both support
gap—stop using margin hacks! repeat(auto-fit, minmax())is responsive magic
Start practicing! Take an existing project and refactor it using these principles. You'll quickly develop an intuition for which tool to reach for. And remember: the best layout is the one that's easy to understand and maintain.
