← Back to the Grid Playground
Lesson

CSS Grid, Visually

Grid is the tool for two-dimensional layout — rows and columns at once. Page shells, card galleries, dashboards, image mosaics. This lesson teaches tracks, the fr unit, repeat(), auto-fit, spanning, and named areas, with controls you can click to watch the grid rebuild live.

Step 1

Grid vs Flexbox: two dimensions

Flexbox arranges items along one line (a row or a column). Grid arranges them in two directions at once — a true matrix of rows and columns. You define the structure on the container; items flow into the cells.

Rule of thumb: reach for Flexbox when content dictates the layout (a row of buttons), and Grid when the layout dictates the content (a page shell or gallery you design up front). They pair beautifully — a Grid page with Flexbox inside each cell.
Step 2

Columns & the fr unit

Turn on grid and define columns with grid-template-columns. The fr unit means “one fraction of the free space,” so 1fr 1fr 1fr is three equal columns. Click to change the count:

grid-template-columns: 1fr 1fr 1fr
1
2
3
4
5
6
Mix units freely: 200px 1fr gives a fixed 200px sidebar and a flexible main column. 2fr 1fr makes the first column twice as wide as the second. Items wrap to new rows automatically.
Step 3

repeat() & gap

Typing 1fr 1fr 1fr 1fr gets old. repeat(4, 1fr) says the same thing. And gap sets the gutters — one property for both directions (or row-gap / column-gap separately).

.grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);  4 equal columns
  gap: 16px;                          gutters everywhere
}
repeat() can also take a list: repeat(3, 2fr 1fr) repeats the pattern three times → six columns alternating wide/narrow.
Step 4

Rows: explicit & implicit

You usually let rows create themselves as items wrap, but you can size them too. grid-template-rows sizes rows you define; grid-auto-rows sizes the ones Grid adds automatically.

.grid {
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: 120px;   every new row is 120px tall
}
minmax(100px, auto) as a row size means “at least 100px, but grow if the content needs it” — the safe way to set row heights without clipping.
Step 5

Responsive with auto-fit + minmax()

This is Grid's superpower: a fluid, wrapping gallery with no media queries. repeat(auto-fit, minmax(120px, 1fr)) means “fit as many ~120px columns as you can, then stretch them to fill.” Toggle it and resize the window:

grid-template-columns: repeat(3, 1fr)
1
2
3
4
5
6
7
8
Memorize this line: grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); — it's the responsive card grid you'll use on almost every project. auto-fill is the close cousin that keeps empty tracks instead of stretching.
Step 6

Making items span cells

Items can cover more than one cell. grid-column: span 2 makes an item two columns wide; grid-row: span 2 makes it two rows tall. Click to grow the orange item:

item 1 → grid-column: span 1
1
2
3
4
5
6
7
8
.feature { grid-column: span 2; }   two columns wide
.hero    { grid-column: 1 / -1; }   first line to last — full width
grid-column: 1 / -1 is the handy “span the whole row” trick — line 1 to the last line, whatever the column count.
Step 7

Named template areas

For page layouts, Grid lets you draw the layout in ASCII with grid-template-areas, then drop each element into its named area. It's the most readable layout CSS there is:

header
sidebar
main
footer
.app {
  display: grid;
  grid-template-columns: 160px 1fr;
  grid-template-areas:
    "header  header"
    "sidebar main"
    "footer  footer";
}
header  { grid-area: header; }
.side   { grid-area: sidebar; }
To make it responsive, just redefine grid-template-areas inside a media query — stack everything into one column on phones (this diagram does exactly that; narrow your window to see it restack).
Step 8

Aligning the grid & its items

Grid has two alignment dimensions, each with two scopes — aligning items inside their cells, and aligning the whole grid inside the container when there's leftover space.

PropertyAligns
justify-itemsItems within their cell, horizontally.
align-itemsItems within their cell, vertically.
place-itemsShorthand for both — place-items: center centers everything.
justify-contentThe whole grid within the container, horizontally.
align-contentThe whole grid within the container, vertically.
justify-self / align-selfOverride alignment for one specific item.
The one to remember: place-items: center on a grid centers its children both ways — the cleanest centering technique in CSS.
Step 9

Patterns you'll reuse

Responsive card gallery

.cards { display: grid; gap: 20px;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }

Holy-grail page shell

.app { display: grid; min-height: 100vh;
  grid-template: auto 1fr auto / 220px 1fr; }   rows / columns

Dead-center a single element

.center { display: grid; place-items: center; min-height: 100vh; }

Feature tile that spans two columns

.gallery .feature { grid-column: span 2; grid-row: span 2; }
Step 10

Grid cheat sheet

Where next

Keep going