CSS Grid is the most powerful layout system in CSS. This tutorial takes you from your first grid to complex, real-world layouts — and every concept comes with a live demo you can see rendered right here in the browser, sitting next to the code that produces it. Resize the window or open your browser’s grid inspector to watch each example respond.
How Grid Thinks
Flexbox lays out content in a single direction — a row or a column. Grid works in two dimensions at once: you define columns and rows, then place items into the cells they create. That makes Grid the right tool for page-level layouts, dashboards, image galleries, and any design where alignment matters both across and down.
Every demo below is real CSS Grid rendered by your browser — not a screenshot. Each one sits next to the code that produces it, so you can read the rule and see its effect in the same place.
Getting Started with Grid
Creating a Grid Container
Set display: grid on a container, declare your columns, and the children become grid items automatically.
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: auto;
gap: 20px;
}
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
</div>
Six items flow into three equal columns, wrapping onto a new row automatically. The gap is the gutter you can see between every cell.
Essential Grid Properties
Defining Columns and Rows
grid-template-columns accepts fixed lengths, flexible fractions, or a mix of both. These are the patterns you will reach for most often.
/* Fixed sizes */
grid-template-columns: 200px 200px 200px;
/* Flexible sizes */
grid-template-columns: 1fr 2fr 1fr;
/* Mixed */
grid-template-columns: 200px 1fr 200px;
/* Repeat function */
grid-template-columns: repeat(4, 1fr);
/* Auto-fit for responsive grids */
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
The 1fr 2fr 1fr pattern splits the row into four parts and gives the middle column two of them:
Mixing fixed and flexible tracks pins the outer columns and lets the center absorb the rest of the width:
The fr Unit and minmax()
The fr unit represents one fraction of the leftover space in the container, distributed after fixed tracks and gaps are subtracted. Combine it with minmax(min, max) to give a track a floor and a ceiling: minmax(250px, 1fr) never lets a column shrink below 250px but allows it to grow and fill space. This pairing is the engine behind responsive grids that need no media queries.
auto-fit vs auto-fill
Both keywords build as many columns as will fit, but they treat leftover space differently. auto-fill keeps empty “phantom” tracks, so your items stay at their minimum width. auto-fit collapses empty tracks to zero, letting the real items stretch to fill the row. Drop the same three items into each and the difference is obvious on a wide screen:
/* Items stretch to fill the row */
grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
/* Empty tracks are preserved; items stay narrow */
grid-template-columns: repeat(auto-fill, minmax(110px, 1fr));
auto-fill leaves room for columns that have no item yet.Grid Gap
gap sets the gutter between tracks. Use the shorthand for equal spacing, or set the row and column gutters independently.
/* Shorthand */
gap: 20px;
/* Individual */
row-gap: 20px;
column-gap: 30px;
Placing Items on the Grid
Grid Lines
Grid tracks are bounded by numbered lines, starting at 1 on the left/top. -1 is shorthand for the last line, so grid-column: 1 / -1 spans every column. Use line numbers to make an item straddle multiple tracks.
.header {
grid-column: 1 / -1; /* Span all columns */
grid-row: 1;
}
.sidebar {
grid-column: 1;
grid-row: 2 / 4; /* Span rows 2 and 3 */
}
.main {
grid-column: 2 / -1;
grid-row: 2;
}
Named Grid Areas
For layouts you can describe in words, grid-template-areas lets you draw the layout as ASCII art, then assign each item to a named region. It is the most readable way to express a page skeleton.
.container {
display: grid;
grid-template-columns: 250px 1fr;
grid-template-rows: auto 1fr auto;
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;
}
Try It: Interactive Grid Playground
Reading about tracks is one thing — feeling them snap into place is another. Click a value below to rewrite grid-template-columns on the live grid and watch the eight items reflow instantly.
grid-template-columns: repeat(4, 1fr);
Real-World Layout Examples
Card Grid (Auto-responsive)
The single most useful Grid recipe: a card grid that reflows on its own, no breakpoints required. auto-fill plus minmax decides how many cards fit per row as the container resizes.
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 24px;
padding: 24px;
}
.card {
background: white;
border-radius: 12px;
padding: 20px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
Holy Grail Layout
The classic application shell — header, footer, a main column, and two flanking rails. Named areas make it a four-line declaration, and a single media query collapses it into a single column on small screens.
.holy-grail {
display: grid;
grid-template:
"header header header" auto
"nav main aside" 1fr
"footer footer footer" auto
/ 200px 1fr 200px;
min-height: 100vh;
}
@media (max-width: 768px) {
.holy-grail {
grid-template:
"header" auto
"nav" auto
"main" 1fr
"aside" auto
"footer" auto
/ 1fr;
}
}
Magazine Layout
Editorial layouts mix a large feature tile with smaller stories. Span the feature across two columns and two rows, let a secondary block run wide, and allow the rest to auto-place around them.
.magazine {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(3, 200px);
gap: 16px;
}
.featured {
grid-column: 1 / 3;
grid-row: 1 / 3;
}
.secondary {
grid-column: 3 / 5;
}
Advanced Techniques
Alignment
Grid gives you two axes of control. justify-* works along the row (horizontal), align-* along the column (vertical). Set defaults on the container with justify-items/align-items, then override a single item with justify-self/align-self.
.container {
/* Align all items within their cells */
justify-items: center; /* horizontal */
align-items: center; /* vertical */
/* Align the whole grid within the container */
justify-content: center;
align-content: center;
}
.item {
/* Override one item */
justify-self: end;
align-self: start;
}
Implicit Grid and Dense Packing
When items land outside your explicit tracks, Grid creates implicit rows to hold them — size those with grid-auto-rows. Set grid-auto-flow: dense and Grid backfills earlier gaps with later items that fit, producing a tight, masonry-like pack.
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
/* Size auto-created rows */
grid-auto-rows: minmax(100px, auto);
/* Backfill holes with items that fit */
grid-auto-flow: dense;
}
Subgrid
When a grid item is itself a grid, grid-template-columns: subgrid (or subgrid for rows) lets the child reuse the parent’s track lines instead of defining its own. It is the cleanest fix for card grids where every card’s header, body, and footer must line up across the whole row regardless of content length. Subgrid is now supported across all major browsers.
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
}
.card {
display: grid;
grid-row: span 3;
grid-template-rows: subgrid; /* share the parent's row lines */
}
Browser DevTools
Your browser’s grid inspector turns these abstractions into something you can see:
- Open DevTools (F12, or Cmd+Opt+I on macOS).
- Select the grid container in the Elements panel.
- Click the grid badge next to it to toggle the overlay.
- Enable line numbers and area names to label every track.
Chrome and Firefox both render the overlay live, so editing grid-template-columns in the Styles panel updates the lines as you type — try it on any demo on this page.
Conclusion
CSS Grid makes complex layouts simple. Start with display: grid and a column template, lean on fr and minmax for responsive sizing, reach for named areas when a layout reads better as a picture, and finish with alignment and dense packing for the details. With the patterns above — and the live demos to experiment against — you have everything you need to build sophisticated layouts with confidence.
For the complete property reference, keep MDN’s CSS Grid Layout guide close while you practice.
Related Reading
- Build a Responsive Documentation Card Grid — put
auto-fitandminmax()to work on a real documentation index. - Accessible Form Patterns: Labels, Errors, and Helpful States — pair these layouts with forms everyone can use.
- Bootstrap 5 integration — how the theme’s flexbox-based Bootstrap grid complements native CSS Grid.
- Customizing layouts — the theme’s layout hierarchy and where your grids fit in.
Comments