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.
- Tracks — the columns and rows you define.
- Cells — where a column and row cross.
- Gap — the gutters between tracks.
- Lines — the numbered grid lines you place items against.
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:
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.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.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.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(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.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:
.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.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:
.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; }
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).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.
| Property | Aligns |
|---|---|
| justify-items | Items within their cell, horizontally. |
| align-items | Items within their cell, vertically. |
| place-items | Shorthand for both — place-items: center centers everything. |
| justify-content | The whole grid within the container, horizontally. |
| align-content | The whole grid within the container, vertically. |
| justify-self / align-self | Override alignment for one specific item. |
place-items: center on a grid centers its children both ways — the cleanest centering technique in CSS.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; }
Grid cheat sheet
-
display: grid+grid-template-columnsgo on the parent -
fr= a share of free space;repeat(n, 1fr)= n equal columns - Space tracks with
gap, never margins - Responsive galleries:
repeat(auto-fit, minmax(200px, 1fr)) - Span cells with
grid-column: span 2or1 / -1for full width - Page layouts read best with
grid-template-areas - Center anything with
place-items: center