CSS Grid vs Flexbox: When to Use Each Layout System (with Code Examples)
CSS Grid and Flexbox are both powerful layout systems, and modern web development uses them together constantly. But knowing when to reach for each one will make your layouts cleaner, more maintainable, and less reliant on hacks. Here is the definitive guide to choosing between them.
The Core Difference: 1D vs 2D
The fundamental distinction is simple:
- Flexbox is a one-dimensional layout system. It controls layout in a single direction: either a row or a column, but not both at the same time.
- CSS Grid is a two-dimensional layout system. It controls layout in both rows and columns simultaneously.
This does not mean Flexbox cannot handle 2D layouts (with wrapping, it can), but it handles each row or column independently. Grid treats the entire 2D space as one cohesive layout.
When to Use Flexbox
Flexbox excels at distributing space along a single axis. Use it for:
- Navigation bars - horizontal menu items with flexible spacing
- Button groups - a row of buttons that need equal spacing
- Centering - vertically and horizontally centering a single element
- Card rows - items that flow and wrap naturally
- Form layouts - label/input pairs in a row
- Media objects - image + text side by side
Flexbox Example: Navigation Bar
.nav {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1rem 2rem;
}
.nav-links {
display: flex;
gap: 1.5rem;
list-style: none;
}
.nav-links a {
text-decoration: none;
color: inherit;
}
Flexbox Example: Centering
.center-wrapper {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
When to Use CSS Grid
Grid is the right choice when you need to control both rows and columns, or when the layout structure should be defined by the container rather than the content. Use it for:
- Full page layouts - header, sidebar, main, footer arrangements
- Magazine-style layouts - content blocks of varying sizes in a grid
- Dashboard layouts - widgets arranged in a precise grid
- Overlapping elements - placing items on top of each other
- Responsive card grids - equal-sized cards that reflow based on screen width
Essential Grid Concepts
grid-template-columns and the fr Unit
The fr unit represents a fraction of the available space, similar to flex-grow in Flexbox:
.grid {
display: grid;
grid-template-columns: 1fr 2fr 1fr;
gap: 1rem;
}
/* Creates 3 columns: 25% | 50% | 25% of available space */
You can mix fixed and flexible units:
.grid {
display: grid;
grid-template-columns: 250px 1fr;
gap: 1rem;
}
/* Fixed 250px sidebar + flexible main content */
Named Grid Areas
Named grid areas are one of CSS Grid's most powerful features. They let you define layouts semantically:
.layout {
display: grid;
grid-template-columns: 200px 1fr 200px;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"header header header"
"sidebar main aside"
"footer footer footer";
min-height: 100vh;
gap: 1rem;
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
.aside { grid-area: aside; }
.footer { grid-area: footer; }
This "holy grail" layout is readable, maintainable, and easy to restructure for responsive design by redefining the grid-template-areas in a media query.
auto-fill vs auto-fit
These two keywords look similar but behave differently when there is extra space:
/* auto-fill: creates as many tracks as fit, even if empty */
.grid-fill {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 1rem;
}
/* auto-fit: collapses empty tracks, stretching items to fill */
.grid-fit {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1rem;
}
With 3 items in a container that could fit 5 columns: auto-fill creates 5 columns (2 empty), while auto-fit creates 3 columns that stretch to fill the container. For most card grid use cases, auto-fit is what you want.
Common Layout Patterns
Responsive Card Grid
The most common Grid pattern: cards that automatically reflow based on available space, with no media queries needed:
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 1.5rem;
padding: 1.5rem;
}
This creates cards that are at least 280px wide and expand to fill available space. As the viewport narrows, columns drop off naturally.
12-Column Layout
.twelve-col {
display: grid;
grid-template-columns: repeat(12, 1fr);
gap: 1rem;
}
.span-full { grid-column: 1 / -1; } /* all 12 columns */
.span-half { grid-column: span 6; } /* 6 columns */
.span-third { grid-column: span 4; } /* 4 columns */
.span-quarter { grid-column: span 3; } /* 3 columns */
Responsive Holy Grail with Media Query
.page {
display: grid;
grid-template-areas:
"header"
"main"
"sidebar"
"footer";
grid-template-columns: 1fr;
}
@media (min-width: 768px) {
.page {
grid-template-columns: 250px 1fr;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
}
}
Can You Use Both Together?
Absolutely. Using Flexbox inside Grid cells is common and correct. Grid defines the overall page structure, and Flexbox handles alignment within individual components:
.page {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 1.5rem;
}
.card {
display: flex;
flex-direction: column;
justify-content: space-between;
padding: 1.5rem;
border: 1px solid #e5e7eb;
border-radius: 0.5rem;
}
.card-footer {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: auto;
}
Here, Grid handles the card layout across the page, and Flexbox handles the internal card structure, pushing the footer to the bottom.
Quick Decision Table
| Scenario | Use | Why |
|---|---|---|
| Navigation bar | Flexbox | Single row, flexible spacing |
| Center an element | Flexbox | Simpler syntax for 1D centering |
| Card grid with auto-reflow | Grid | 2D control, auto-fit handles responsiveness |
| Full page layout | Grid | Named areas for header/sidebar/main/footer |
| Button group | Flexbox | Single row, gap property |
| Dashboard widgets | Grid | Precise 2D placement, spanning |
| Items inside a grid cell | Flexbox | 1D alignment within the cell |
| Overlapping elements | Grid | Items can share grid cells |
Try our CSS Grid Generator to visually build grid layouts and export production-ready CSS code.
Frequently Asked Questions
Is CSS Grid replacing Flexbox?
No. Grid and Flexbox solve different problems and are designed to work together. Flexbox is still the best choice for one-dimensional layouts and component-level alignment. Grid is better for two-dimensional page layouts. Modern CSS uses both extensively, and neither is going away.
Which has better browser support?
Both CSS Grid and Flexbox have excellent browser support as of 2024. CSS Grid is supported in all modern browsers including Chrome, Firefox, Safari, and Edge. Flexbox has been supported even longer. The only concern would be very old browsers like IE 11, which has partial and buggy Grid support. For virtually all production websites today, both are safe to use.
Can I nest Grid inside Flexbox or Flexbox inside Grid?
Yes, and this is a common pattern. A typical approach is to use Grid for the overall page layout, then use Flexbox for components within grid cells (like card internals, navigation bars, or button groups). You can also nest Grid inside Flexbox, though this is less common. There is no performance penalty for nesting layout systems.
What is the CSS gap property, and does it work with both?
The gap property sets spacing between grid items or flex items. It originally only worked with Grid (as grid-gap), but now works with Flexbox in all modern browsers. It replaces the need for margin hacks and is the recommended way to add spacing between items in both layout systems.
How do I make a responsive grid without media queries?
Use grid-template-columns: repeat(auto-fit, minmax(MIN_WIDTH, 1fr)) where MIN_WIDTH is the smallest acceptable column width (e.g., 250px). This creates a grid that automatically adjusts the number of columns based on container width. No media queries needed. The auto-fit keyword collapses empty columns, and minmax() ensures items never get smaller than your minimum width.
Should I use CSS Grid for a simple two-column layout?
Either works, but Grid is often cleaner for two-column layouts where you want precise width control. grid-template-columns: 250px 1fr gives you a fixed sidebar and flexible main area in one line. Flexbox can achieve the same result but requires setting flex-basis or width on the sidebar and flex: 1 on the main area, which is slightly more verbose.