CSS Grid: The Complete Guide to Layout Mastery (2026)
CSS Grid changed how we build layouts forever. No more floats, no more hacks — just clean, powerful layout control.
The Mental Model
CSS Grid = Two-dimensional layout system
Think of it as a spreadsheet:
┌─────┬─────┬─────┬─────┐
│ │ │ │ │ ← Rows (horizontal)
│ 1 │ 2 │ 3 │ 4 │
├─────┼─────┼─────┼─────┤
│ │ │ │ │
│ 5 │ 6 │ 7 │ 8 │ ← Columns (vertical)
├─────┼─────┼─────┼─────┤
│ │ │ │ │
│ 9 │ 10 │ 11 │ 12 │
└─────┴─────┴─────┴─────┘
You define:
1. The grid container (display: grid)
2. Columns and rows (template)
3. Where items go (placement)
Essential Properties
/* === Container: Define the grid === */
.dashboard {
display: grid;
/* Column definition */
grid-template-columns: 250px 1fr 200px; /* Fixed - Fluid - Fixed */
grid-template-columns: repeat(4, 1fr); /* 4 equal columns */
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); /* Responsive! */
/* Row definition */
grid-template-rows: auto 1fr auto; /* Content-fit - Fill remaining - Content-fit */
grid-template-rows: minmax(100px, auto); /* At least 100px, grow if needed */
/* Gap between cells */
gap: 16px; /* Row + column gap */
row-gap: 12px; /* Row gap only */
column-gap: 20px; /* Column gap only */
/* Alignment within the grid area */
justify-items: start | center | end | stretch; /* Horizontal alignment of items */
align-items: start | center | end | stretch; /* Vertical alignment of items */
/* Entire grid content placement */
justify-content: start | center | end | space-between | space-around | space-evenly;
align-content: start | center | end | space-between | space-around | space-evenly;
}
/* === Items: Place them in the grid === */
.header {
grid-column: 1 / -1; /* Span all columns (from first to last) */
grid-row: 1 / 2; /* Row 1 only */
}
.sidebar {
grid-column: 1 / 2; /* First column only */
grid-row: 2 / 4; /* Span rows 2 and 3 */
}
.main-content {
grid-column: 2 / 3; /* Second column */
grid-row: 2 / 4; /* Span rows 2-3 */
}
/* Shorthand for both column AND row placement */
.featured {
grid-area: 2 / 2 / 4 / 4; /* row-start / col-start / row-end / col-end */
}
Real-World Layouts
/* === Layout 1: Dashboard (classic admin layout) === */
.app-layout {
display: grid;
grid-template-columns: 260px 1fr;
grid-template-rows: 64px 1fr auto;
grid-template-areas:
"sidebar header"
"sidebar main"
"sidebar footer";
min-height: 100vh;
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
.footer { grid-area: footer; }
/* Mobile: stack everything vertically */
@media (max-width: 768px) {
.app-layout {
grid-template-columns: 1fr;
grid-template-areas:
"header"
"main"
"footer";
.sidebar { display: none; } /* Or show as drawer */
}
}
/* === Layout 2: Card Grid (responsive gallery) === */
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 24px;
padding: 16px;
}
/* Automatically adjusts number of columns based on available width!
1200px viewport → 3 columns
900px viewport → 2 columns
350px viewport → 1 column */
/* === Layout 3: Holy Grail (header + footer + 3 columns) === */
.holy-grail {
display: grid;
grid-template-columns: 200px 1fr 180px;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"header header header"
"nav main aside"
"footer footer footer";
min-height: 100vh;
}
/* === Layout 4: Magazine/News Layout === */
.magazine-layout {
display: grid;
grid-template-columns: 2fr 1fr;
grid-template-rows: auto auto 1fr auto;
grid-template-areas:
"hero hero"
"featured sidebar"
"articles sidebar"
"footer footer";
gap: 32px;
}
.hero { grid-area: hero; }
.featured { grid-area: featured; }
.articles {
grid-area: articles;
display: grid;
grid-template-columns: repeat(2, 1fr); /* Nested grid! */
gap: 20px;
}
.sidebar { grid-area: sidebar; }
.footer { grid-area: footer; }
/* === Layout 5: Form alignment (no more tables!) === */
.form-grid {
display: grid;
grid-template-columns: 140px 1fr;
gap: 16px;
align-items: center;
max-width: 500px;
}
.form-grid label { text-align: right; font-weight: 600; }
.form-grid input,
.form-grid select,
.form-grid textarea { width: 100%; }
.form-grid .full-width {
grid-column: 1 / -1; /* Span across label + input columns */
}
@media (max-width: 480px) {
.form-grid {
grid-template-columns: 1fr; /* Stack on mobile */
}
.form-grid label { text-align: left; }
}
Advanced Techniques
/* === Implicit Grid (auto-created rows/columns) === */
.grid-auto {
display: grid;
grid-template-columns: repeat(3, 100px);
gap: 10px;
/* If you place an item beyond defined columns/rows,
Grid creates implicit ones automatically */
grid-auto-columns: 80px; /* Width of implicit columns */
grid-auto-rows: minmax(60px, auto); /* Height of implicit rows */
grid-auto-flow: row; /* or 'column' — fill direction */
}
/* === Named Lines (more readable than numbers) === */
.named-lines {
display: grid;
grid-template-columns: [sidebar-start] 240px [sidebar-end main-start] 1fr [main-end aside-start] 200px [aside-end];
grid-template-rows: [header-start] 70px [header-end content-start] 1fr [content-end];
}
.nav { grid-column: sidebar-start / sidebar-end; }
.content { grid-column: main-start / main-end; }
/* === Subgrid (child inherits parent's track definitions!) === */
.card {
display: grid;
grid-template-columns: 1fr 2fr;
gap: 0;
}
.card-header {
grid-column: 1 / -1; /* Spans full width */
background: #f5f5f5;
padding: 16px;
/* Use subgrid to align with parent's rows */
display: grid;
grid-row: subgrid;
grid-template-rows: subgrid; /* Inherits parent's row heights! */
}
/* === Overlapping Items (layering without absolute positioning) === */
.hero-section {
display: grid;
grid-template-columns: 1fr;
grid-template-rows: 400px;
}
.hero-bg {
grid-area: 1 / 1;
background: url('hero.jpg') center/cover;
z-index: 1;
}
.hero-overlay {
grid-area: 1 / 1;
background: rgba(0, 0, 0, 0.4);
z-index: 2;
}
.hero-content {
grid-area: 1 / 1;
z-index: 3;
color: white;
display: flex;
flex-direction: column;
justify-content: center;
padding: 40px;
}
/* All three occupy the same cell! Z-index controls visibility order. */
/* === Aspect Ratio Cards === */
.aspect-ratio-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px;
}
.aspect-card {
aspect-ratio: 16 / 9; /* Maintains aspect ratio regardless of width */
overflow: hidden;
border-radius: 8px;
}
/* === Masonry-like effect (with limitations) === */
.masonry-workaround {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: 10px; /* Small base unit */
gap: 16px;
}
.masonry-item:nth-child(1) { grid-row: span 25; } /* 250px tall */
.masonry-item:nth-child(2) { grid-row: span 35; } /* 350px tall */
.masonry-item:nth-child(3) { grid-row: span 20; } /* 200px tall */
/* Note: True masonry needs JS or the upcoming masonry spec */
Grid vs Flexbox: When to Use Which
┌─────────────────────────────────────────────────┐
│ Use GRID when: │
│ • Need 2D layout (rows AND columns) │
│ • Building overall page structure │
│ • Items need to overlap │
│ • Complex alignment requirements │
│ • Example: dashboard, card grid, magazine │
├─────────────────────────────────────────────────┤
│ Use FLEXBOX when: │
│ • Need 1D layout (row OR column) │
│ • Content-driven sizing │
│ • Aligning items in a single line │
│ • Centering (the classic use case!) │
│ • Example: nav bar, form elements, button group │
└─────────────────────────────────────────────────┘
They work TOGETHER:
.grid-container { display: grid; }
.flex-inside-grid { display: flex; } /* Totally fine! */
What's your favorite Grid trick? What layout challenge are you still struggling with?
Follow @armorbreak for more practical developer guides.
Top comments (0)