Overview
Grid lays out two-dimensional structure: rows and columns that line up. Use it for page shells, dashboards, card galleries, and forms where labels and inputs align across rows. For a single row or column, use css-flexbox. The umbrella page is css.
Use grid when alignment must survive across rows
A single axis with items that grow and shrink is flex; anything with both axes locked, or alignment that must hold across rows, is grid. Nest flex inside grid and the reverse as needed; do not force one primitive to do both jobs.
.page { display: grid; grid-template-columns: 240px 1fr; grid-template-rows: auto 1fr auto; min-block-size: 100dvh; }Size tracks with fr, minmax(), and auto-fill
Prefer intrinsic sizing so the layout absorbs content variance. 1fr shares free space after intrinsic sizes resolve; minmax(min, max) clamps a track; repeat(auto-fill, minmax(16rem, 1fr)) makes a responsive card grid in one line.
.cards { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr)); }Use auto-fit instead of auto-fill only when surviving items should stretch to fill the last row.
Use minmax(0, 1fr) to stop overflow
1fr is minmax(auto, 1fr), so a track will not shrink below its content’s minimum size. A 200px 1fr grid with a wide child therefore overflows. Use 200px minmax(0, 1fr), or set min-width: 0 on the grid item.
Align nested content with subgrid
grid-template-rows: subgrid makes a nested grid reuse the parent’s tracks, so card titles, bodies, and footers line up across cards regardless of content height. Subgrid has been Baseline widely available since March 2026.
.cards { display: grid; grid-template-columns: repeat(3, 1fr); grid-template-rows: auto 1fr auto; }
.card { display: grid; grid-row: span 3; grid-template-rows: subgrid; }Name areas and lines
Numbered lines break when a column is added. Name the areas and place items by name; see css-grid-areas.
.page {
display: grid;
grid-template-columns: 240px 1fr;
grid-template-areas: "sidebar header" "sidebar main" "sidebar footer";
}
.main { grid-area: main; }Keep layout on the container
The container owns tracks and gaps; items own content. Do not put width, margin-left: auto, or flex on items that already sit in tracks. Change grid-template-columns on the container instead.
Use gap, not margins
gap, row-gap, and column-gap are the gutters. Margins on children leak through nested layouts. Tailwind’s gap-4 compiles to the same property (tailwind).
Avoid common pitfalls
- Items overflowing tracks. Grid items default to
min-width: auto; setmin-width: 0on items that should compress. - Counting numeric lines. Name lines or areas.
- Reordering with
order,grid-row-start, or areas. Focus and screen-reader order follow the DOM, not the layout; keep the DOM order sensible (accessibility).