Web development
Grid with named areas: the layout written as a map
Named areas write the layout as an ASCII map and keep the same names at every breakpoint. When they pay off, how to read them and where they break.
Key points
- Every name in `grid-template-areas` must form a rectangle, or the declaration is dropped.
- At a breakpoint you rewrite the map; children keep the same `grid-area`.
- `grid-template-areas` is not animatable: a transition between two maps snaps.
Named areas let you write the layout as a map inside grid-template-areas. They pay off when page regions have a stable name, header, nav, main, footer, and must stay recognisable at every breakpoint.
The map
.shell {
display: grid;
grid-template-columns: 16rem minmax(0, 1fr);
grid-template-rows: auto 1fr auto;
grid-template-areas:
"nav header"
"nav main"
"nav footer";
gap: 1rem;
min-height: 100dvh;
}
.nav { grid-area: nav; }
.header { grid-area: header; }
.main { grid-area: main; }
.footer { grid-area: footer; }
The quotes hold a row of tracks; each word is an area name and each dot is an empty cell. The number of strings sets the rows, the number of names per string sets the columns: the map is also the track declaration.
The breakpoint rewrites the map, not the children
@media (max-width: 48rem) {
.shell {
grid-template-columns: 1fr;
grid-template-rows: auto auto 1fr auto;
grid-template-areas:
"header"
"nav"
"main"
"footer";
}
}
The components stay put: grid-area: nav is unchanged, and the DOM order is still the reading order. That is the gain over numeric coordinates, which must be rewritten in every media query.
Three mistakes that void the declaration
- A name shaped like an L: the area is not a rectangle and the browser ignores the whole property.
- A name repeated in two non-adjacent spots: the second use is valid, but the first never becomes a rectangle.
- Rows of different lengths: the browser fills with implicit cells and the columns stop matching.
The record I use as an example
A product grid solved with named areas is in the catalogue: grid-ecommerce-01. The primitives for the cards sit in card and the hero category covers the top of the page. The catalogue holds 1,556 blocks and 111,985 components from 1,472 libraries (1 November 2026).
How to check in ten seconds
# quante mappe di layout esistono già nel progetto
grep -rn "grid-template-areas" --include="*.css" src/ | wc -l
# il layout non deve scorrere in orizzontale a 320 px
npx playwright screenshot --viewport-size=320,800 http://localhost:3000 mobile.png
The known limit
Named areas do not animate: grid-template-areas is not an interpolable property, so a transition between two maps snaps. If the change must be smooth, animate the children with transform or use view transitions.
To pick the layout model see Flexbox or Grid. The 12-column utility version is in a 12-column Tailwind grid; the comparison between utilities and CSS Modules is Tailwind vs CSS Modules.
Frequently asked questions
Do named areas work inside a subgrid?
Named lines do: a subgrid inherits line names on the shared axis. Areas do not, because grid-template-areas describes tracks the subgrid does not own and must be restated.
Why did the layout disappear after an edit?
Almost always a name no longer forms a rectangle. The browser drops the whole grid-template-areas declaration and normal flow returns, with no console error.
Named areas or grid-column with numbers?
Areas when regions have a name you reuse across breakpoints. Numbers when the grid is generated by a loop and every name would be different.
Do areas adapt to right-to-left languages?
Yes. Tracks follow the writing direction, so with dir="rtl" the first column of the map appears on the right without touching the CSS.
Can I leave a cell empty?
Yes, with a dot. An empty cell receives no content but still occupies the track, so the spacing of the map holds.