grid-template-areas: named layout regions
Named grid areas let you sketch your layout in CSS as if you were drawing it on graph paper. The result is the most readable way to define page structure.
The basic syntax
grid-template-areas accepts a series of quoted strings. Each string represents one row. Each word in a string names a cell. Repeating a name spans that area across multiple columns or rows.
.page {
display: grid;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
grid-template-columns: 16rem 1fr;
grid-template-rows: auto 1fr auto;
min-height: 100dvh;
}
.page__header { grid-area: header; }
.page__sidebar { grid-area: sidebar; }
.page__main { grid-area: main; }
.page__footer { grid-area: footer; }
Each child uses grid-area to claim its named region. The order of children in the HTML no longer matters for visual placement.
Empty cells with the dot token
Use a dot (.) to leave a cell empty. Multiple dots can be used for readability — ... counts as a single empty cell, same as ..
.dashboard {
display: grid;
grid-template-areas:
"nav nav nav"
"stats ... chart"
"table table table";
grid-template-columns: 1fr 2rem 1fr;
grid-template-rows: auto 1fr auto;
gap: 1.5rem;
}
/* The middle cell in row 2 is empty — acts as a visual gutter.
This is an alternative to using gap when you need
different spacing in different areas. */
Responsive layouts with area rearrangement
The real power of named areas shows up in responsive design. You can completely rearrange the layout in a media query by redefining only grid-template-areas and the track definitions. No changes to the HTML, no repositioning individual items.
/* Mobile: single column stack */
.page {
display: grid;
grid-template-areas:
"header"
"main"
"sidebar"
"footer";
grid-template-columns: 1fr;
}
/* Desktop: sidebar layout */
@media (min-width: 60rem) {
.page {
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
grid-template-columns: 16rem 1fr;
grid-template-rows: auto 1fr auto;
}
}
Implicit named lines
When you define a named area, the browser automatically creates named lines around it. An area called main creates lines called main-start and main-end on both axes. You can reference these lines directly for precise placement.
.page {
grid-template-areas:
"header header"
"nav main"
"footer footer";
grid-template-columns: 14rem 1fr;
}
/* Place an overlay spanning from main-start to the end */
.overlay {
grid-column: main-start / -1;
grid-row: main-start / footer-start;
background: oklch(0.1 0.02 260 / 0.8);
}
Combining areas with track sizing
Named areas work alongside all Grid track-sizing features: minmax(), fr units, auto, and fixed lengths. Define the areas for placement and the track templates for sizing.
.app {
display: grid;
grid-template-areas:
"toolbar toolbar toolbar"
"nav content aside"
"nav content aside";
grid-template-columns: minmax(12rem, 16rem) 1fr minmax(14rem, 20rem);
grid-template-rows: auto 1fr;
gap: 1rem;
height: 100dvh;
}
.app__toolbar { grid-area: toolbar; }
.app__nav { grid-area: nav; }
.app__content { grid-area: content; overflow-y: auto; }
.app__aside { grid-area: aside; }
Rules and common mistakes
Named areas must form rectangles. L-shapes, T-shapes, and other non-rectangular regions are invalid and the entire declaration will be ignored.
/* VALID — "hero" spans two columns, forming a rectangle */
grid-template-areas:
"hero hero"
"left right";
/* INVALID — "hero" forms an L-shape */
grid-template-areas:
"hero sidebar"
"hero hero";
/* The browser ignores this entire declaration */
/* VALID — every row must have the same number of cells */
grid-template-areas:
"a b c"
"d e f";
/* INVALID — different column counts per row */
grid-template-areas:
"a b"
"c d e";
- All rows must have the same number of columns.
- Named areas must form rectangles — no L-shapes or diagonals.
- Area names are case-sensitive:
Headerandheaderare different areas. - Use
grid-areaon children, notgrid-row/grid-column, to place items in named areas.