Grid vs Flexbox: When to Use Each
Use CSS Grid when you need two-dimensional control (rows AND columns). Use Flexbox when you're laying out items in a single row or column. The two work best together: Grid for page-level layout, Flexbox for component-level layout.
Grid vs Flexbox at a Glance
| Feature | CSS Grid | Flexbox |
|---|---|---|
| Dimensions | 2D (rows + columns) | 1D (row or column) |
| Content flow | Grid defines structure | Content defines structure |
| Best for | Page layouts, galleries | Nav bars, button groups |
| Alignment | Both axes always | Cross-axis only |
| Browser support | 97%+ globally | 99%+ globally |
Grid Basics: Columns and Rows
/* Define a 3-column grid */
.container {
display: grid;
grid-template-columns: 200px 1fr 200px;
grid-template-rows: auto 1fr auto;
gap: 1rem;
}
/* fr unit = fraction of remaining space */
.container {
grid-template-columns: 1fr 2fr 1fr; /* 25% 50% 25% */
}
/* repeat() shorthand */
.container {
grid-template-columns: repeat(3, 1fr); /* 3 equal columns */
grid-template-rows: repeat(2, minmax(100px, auto));
}
grid-template-areas: Named Layout
The most readable way to define a page layout. Name each area and assign elements to them.
.layout {
display: grid;
grid-template-columns: 240px 1fr;
grid-template-rows: 60px 1fr 60px;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
min-height: 100vh;
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
.footer { grid-area: footer; }
/* Stack on mobile */
@media (max-width: 768px) {
.layout {
grid-template-columns: 1fr;
grid-template-areas:
"header"
"main"
"sidebar"
"footer";
}
}
auto-fill vs auto-fit: Responsive Grids Without Media Queries
auto-fill creates as many tracks as possible, even if empty. auto-fit collapses empty tracks and expands filled ones. For responsive card grids, auto-fit is almost always what you want.
/* auto-fit: items expand to fill the row */
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 1.5rem;
}
/* auto-fill: keeps ghost columns */
.fixed-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 1.5rem;
}
/* Result: auto-fit with 1 card → card fills full width
auto-fill with 1 card → card stays 280px min */
Placing Items: Lines and Spans
/* Place by line numbers (1-indexed) */
.hero {
grid-column: 1 / 3; /* span columns 1 and 2 */
grid-row: 1 / 2;
}
/* span keyword */
.featured {
grid-column: span 2; /* span 2 columns from current position */
grid-row: span 3;
}
/* Negative lines: count from end */
.full-width {
grid-column: 1 / -1; /* always full width regardless of column count */
}
Grid Alignment
/* Align ALL items in their cells */
.container {
align-items: center; /* vertical in cell */
justify-items: start; /* horizontal in cell */
place-items: center; /* shorthand for both */
}
/* Align the entire grid within the container */
.container {
align-content: space-between; /* vertical distribution */
justify-content: center; /* horizontal distribution */
}
/* Override per-item */
.item {
align-self: end;
justify-self: stretch;
}
Subgrid: Aligning Nested Grids
Subgrid (supported in all modern browsers since 2023) lets child grids inherit the parent's track sizing — essential for aligned card content.
/* Parent grid */
.card-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: auto;
gap: 1rem;
}
/* Each card spans 3 rows and uses subgrid */
.card {
display: grid;
grid-row: span 3;
grid-template-rows: subgrid; /* inherit parent row tracks */
}
/* Now all card headings, bodies, and footers align */
.card-heading { grid-row: 1; }
.card-body { grid-row: 2; }
.card-footer { grid-row: 3; }
Real-World: Magazine Layout
/* 12-column magazine grid */
.magazine {
display: grid;
grid-template-columns: repeat(12, 1fr);
grid-auto-rows: minmax(60px, auto);
gap: 1rem;
}
.hero-story { grid-column: 1 / 9; grid-row: 1 / 4; }
.side-story-1 { grid-column: 9 / 13; grid-row: 1 / 2; }
.side-story-2 { grid-column: 9 / 13; grid-row: 2 / 4; }
.story-strip { grid-column: 1 / -1; grid-row: 4 / 5; }
Common CSS Grid Mistakes
- Using fixed px columns for responsive layouts — use
frunits andminmax()instead. - Over-specifying rows —
grid-auto-rows: minmax(100px, auto)handles dynamic content better than fixed heights. - Forgetting gap vs margin —
gapapplies between grid items, not on the outside edges. Use padding on the container for outer spacing. - Using floats inside a grid — floats have no effect inside grid containers. Use alignment properties.
- Not using
grid-column: 1 / -1for full-width items — it works regardless of how many columns you have.
Frequently Asked Questions
- Does CSS Grid replace Flexbox?
- No — they complement each other. Grid is for 2D layout (page structure, card grids), Flexbox is for 1D layout (navigation rows, button groups). Most modern UIs use both.
- What does fr mean in CSS Grid?
- fr is a fractional unit. 1fr means 'one fraction of the available space'.
repeat(3, 1fr)creates 3 equal-width columns that share the total space after fixed/auto columns are resolved. - How do I center a single item with Grid?
- Set the container to
display: grid; place-items: center;— this is the shortest, most reliable way to center anything in CSS. - Is CSS Grid supported in all browsers?
- Yes — CSS Grid has 97%+ global support. Subgrid reached full support in late 2023 (all evergreen browsers). Safe to use without fallbacks for modern web projects.