This cheatsheet is a lookup page for CSS Grid: the container and item properties, the track sizing functions, how line numbers and named areas work, and layouts you can paste. It is for developers who know what a grid is and need the exact syntax. The confusion it clears up is line numbering: lines are numbered, not cells, so a three-column grid has four column lines.
| Property | Values | Initial | Does |
|---|---|---|---|
| `display` | `grid`, `inline-grid` | n/a | Makes direct children grid items |
| `grid-template-columns` | track list, `none`, `subgrid` | `none` | Defines explicit column tracks |
| `grid-template-rows` | track list, `none`, `subgrid` | `none` | Defines explicit row tracks |
| `grid-template-areas` | one string per row, or `none` | `none` | Names rectangular regions |
| `grid-template` | rows / columns, or areas plus sizes | `none` | Shorthand for the three above |
| `grid-auto-rows` | track size | `auto` | Size of rows created implicitly |
| `grid-auto-columns` | track size | `auto` | Size of columns created implicitly |
| `grid-auto-flow` | `row`, `column`, optionally `dense` | `row` | Fill direction for auto-placed items |
| `gap` | one or two lengths | `normal` | Gutter between rows and columns |
| `justify-items` | `start`, `end`, `center`, `stretch` | `legacy` | Aligns items inside cells on the inline axis |
| `align-items` | `start`, `end`, `center`, `stretch`, `baseline` | `normal` | Aligns items inside cells on the block axis |
| `place-items` | align then justify | see parts | Shorthand for both |
| `justify-content` | `start`, `center`, `space-between`, `space-evenly` and more | `normal` | Places the whole grid when tracks are smaller than the container |
| `grid` | template, or auto-flow forms | `none` | Shorthand that resets every grid property |
| Property | Values | Initial | Does |
|---|---|---|---|
| `grid-column` | `start / end` lines | `auto` | Column placement |
| `grid-row` | `start / end` lines | `auto` | Row placement |
| `grid-column-start`, `grid-column-end` | line number, name, `span n` | `auto` | Longhands of `grid-column` |
| `grid-row-start`, `grid-row-end` | line number, name, `span n` | `auto` | Longhands of `grid-row` |
| `grid-area` | name, or `row-start / col-start / row-end / col-end` | `auto` | Places into a named area or four lines |
| `justify-self` | `start`, `end`, `center`, `stretch` | `auto` | Aligns one item in its cell |
| `align-self` | `start`, `end`, `center`, `stretch`, `baseline` | `auto` | Aligns one item in its cell |
| `order` | integer | `0` | Changes auto-placement order |
| Value | Meaning | Measured example |
|---|---|---|
| `200px` | Fixed length | `200px` stays 200px |
| `1fr` | One share of free space after fixed tracks and gaps | See below |
| `auto` | Fits content, and stretches to fill spare space | Fits the 70px item |
| `min-content`, `max-content` | Narrowest or widest the content can be | Content dependent |
| `minmax(100px, 1fr)` | Never below 100px, grows to its share | Took 430px of 600px |
| `fit-content(300px)` | Content size, capped at 300px | Content dependent |
| `repeat(3, 1fr)` | Three equal tracks | See below |
| `repeat(auto-fill, minmax(200px, 1fr))` | As many 200px-or-wider tracks as fit | Three tracks in 600px |
Computed grid-template-columns read from Chromium 153 in a 600px container:
| You write | Computed value |
|---|---|
| `200px 1fr 2fr` | `200px 133.328px 266.672px` |
| `repeat(3, 1fr)` with `gap: 20px` | `186.656px 186.672px 186.672px` |
| `100px minmax(100px, 1fr) auto` with a 70px third item | `100px 430px 70px` |
| `repeat(auto-fill, minmax(200px, 1fr))` with 5 items | `200px 200px 200px` |
A grid with N columns has N + 1 column lines, numbered 1 to N + 1 from the start edge. Negative numbers count from the end, so -1 is the last line.
| Line values | Covers |
|---|---|
| `grid-column: 1 / 3` | Columns 1 and 2 |
| `grid-column: 2 / -1` | From column 2 to the last column |
| `grid-column: span 2` | Two tracks from the auto-placed start |
| `grid-column: 1 / -1` | Every explicit column |
| `grid-area: 1 / 3 / -1` | Row 1 to the last row line, starting at column line 3 |
.cards { display: grid; gap: 16px; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); }
In a 600px container with five items, Chromium 153 created three 200px columns and two rows. Use it for galleries and product lists.
.page {
display: grid;
grid-template-columns: 150px 1fr;
grid-template-rows: 40px 100px 30px;
grid-template-areas: "head head" "side main" "foot foot";
}
.h { grid-area: head; }
.s { grid-area: side; }
.m { grid-area: main; }
.f { grid-area: foot; }
Measured as x, y, width, height in a 600px container:
head 0, 0, 600, 40
side 0, 40, 150, 100
main 150, 40, 450, 100
foot 0, 140, 600, 30
Each string is one row, and repeating a name across cells makes the area span them. Every named area must be a rectangle.
.g { display: grid; grid-template-columns: repeat(4, 1fr); }
.wide { grid-column: span 2; }
.tail { grid-column: 2 / -1; }
In a 600px container, the .wide item measured 300px wide. The .tail item started at x 150 and measured 450px wide, which is columns 2 to 4.
.g { display: grid; grid-template-columns: repeat(3, 100px); grid-auto-flow: dense; }
.w { grid-column: span 2; }
With items span-2, span-2 and a single cell, default flow put the third item at column 3 of row 2, which is x 200 and y 10. With dense, it moved back to the hole at column 3 of row 1, which is x 200 and y 0. Dense changes visual order, so avoid it when reading order matters.
.g { display: grid; grid-template-columns: 200px; grid-template-rows: 100px; place-items: center; }
A 50px by 20px item landed at x 75 and y 40, which is the exact center of the 200px by 100px cell.
.g { display: grid; grid-template-columns: 100px 100px; grid-auto-rows: 30px; }
Five items produced three rows of 30px each. Without grid-auto-rows, rows created from overflow are auto.
.layout {
display: grid;
grid-template-columns: [full-start] 1fr [content-start] minmax(0, 300px) [content-end] 1fr [full-end];
}
.text { grid-column: content; }
.bleed { grid-column: full; }
In a 600px container, .text measured x 150 and width 300, and .bleed measured x 0 and width 600. Naming the lines content-start and content-end lets grid-column: content select the span between them, so children never need to know the track numbers.
console.log(CSS.supports('grid-template-columns', 'subgrid'));
console.log(CSS.supports('grid-template-rows', 'masonry'));
Output in Chromium 153:
true
false
Subgrid is part of Grid Level 2. The masonry value returned false in the same run, so do not rely on it.
grid-column: 1 / 3 covers two columns, not three. The end number is a line, so use span 2 if you think in cells.grid-template-areas must form rectangles, and rows with different cell counts make the whole declaration invalid. Fix the strings so every row has the same number of cells.grid resets the explicit tracks and the implicit grid properties together, while grid-template leaves the implicit ones alone. After grid-auto-rows: 25px, a later grid: auto-flow 40px / 1fr 1fr made grid-auto-rows compute to 40px in Chromium 153.grid-gap: 7px as an alias and reports 7px 7px for gap. Write gap, which is the standard name.grid-auto-flow: dense fills earlier holes, so DOM order and visual order differ. Keyboard focus follows the DOM.1fr takes what is left after fixed tracks and gaps, so in 200px 1fr 2fr at 600px the fr tracks are 133.328px and 266.672px, not 200px each.repeat(3, 100px) in a wider box.grid-template-rows: masonry returned false from CSS.supports in Chromium 153.