skip to content

How does `grid-template-areas` place items in a CSS grid, and what makes an areas declaration invalid?

level: middleimportance: must knowfreq 68%

answer

  1. the value is a picture
  2. one string per row
  3. dot means an unnamed cell
  4. rectangles only, no L shapes
  5. one bad token drops the whole declaration

basics

~20 s

Each string in grid-template-areas is a row and each token in it is a cell, so the value reads like a picture of the layout. An item is placed by matching grid-area to a name. Every named area must form one solid rectangle and every row must have the same number of cells, or the whole declaration is dropped.

solid answer

~50 s

`grid-template-areas` names cells on the container, and items opt in with `grid-area: <name>`. The value is a list of strings, one per row, whose whitespace-separated tokens name the cell in each column — so the declaration is an ASCII picture of the layout, and rearranging the layout at a breakpoint means rewriting the picture rather than re-deriving line numbers on every child. A `.` token (or a run of dots) marks a deliberately empty cell. Two rules make a declaration valid: every row must have the same number of tokens, and each name must occupy a single contiguous rectangle. An L-shaped or split area is invalid, and because CSS drops invalid declarations wholesale, the grid falls back to having no named areas at all — usually presenting as every item stacking in the first column.

code

css · 14 lines
css
.page {
  display: grid;
  grid-template-columns: 200px 1fr;
  grid-template-rows: auto 1fr auto;
  grid-template-areas:
    "header  header"
    "sidebar main"
    ".....   footer";
}

.page > header { grid-area: header; }
.page > nav    { grid-area: sidebar; }
.page > main   { grid-area: main; }
.page > footer { grid-area: footer; }

go deeper

for a junior

Know that each quoted string is a row, that the tokens name cells, and that a child joins a region with grid-area: name. Be able to write a simple header/sidebar/main/footer map.

for a middle

Explain the two validity rules — equal token counts per row and rectangular areas — what a . means, and that an invalid value drops the entire declaration rather than part of it.

for a senior

Expect a debugging scenario where a layout collapses after an edit. Trace it to a dropped declaration, and demonstrate judgment about when named areas beat line numbers and when they do not scale.

for a principal

Own the tradeoff between a container-owned layout map and item-owned placement. Set the rule for responsive restructuring so visual reordering never drifts away from a sensible source order across breakpoints.

## The idea Line-based placement puts the layout knowledge in the children: each item states which lines it sits between. `grid-template-areas` inverts that. The container draws the map, and each child only says which region it belongs to. ```css .page { display: grid; grid-template-columns: 200px 1fr; grid-template-rows: auto 1fr auto; grid-template-areas: "header header" "sidebar main" "footer footer"; } .page > header { grid-area: header; } .page > nav { grid-area: sidebar; } .page > main { grid-area: main; } .page > footer { grid-area: footer; } ``` Each quoted string is one row of the grid. Each whitespace-separated token inside it names the cell in the corresponding column. The extra spaces used to line the tokens up are purely cosmetic — they make the declaration legible as a diagram, which is the whole point of the syntax. ## How an item matches `grid-area: header` sets all four placement values to the identifier `header`, which resolves to the named area's edges. Nothing in the item's rule mentions rows, columns or counts, so a child can be moved to a completely different part of the layout by editing only the container's map. Items with no matching `grid-area` are not affected by the map at all; they are placed automatically like any other unplaced item. ## Empty cells A `.` token marks a null cell — a cell that belongs to no named area. Any unbroken run of dots counts as a single null cell, so `...` and `.` are equivalent, and people often use a run to keep the columns visually aligned: ```css grid-template-areas: "header header" "..... main"; ``` Null cells are still real grid cells: automatically placed items can land in them, so a `.` reserves nothing. It only means "no named area here". ## The two validity rules **Every row must declare the same number of cells.** `"a a" "b"` is invalid because the second row has one token where the first has two. **Each name must form a single filled rectangle.** All the cells carrying a given name must be contiguous and together make a complete rectangle with no notches. These are invalid: ```css /* L-shaped: 'a' is not a rectangle */ grid-template-areas: "a a" "a ." ; /* split: two disconnected regions share a name */ grid-template-areas: "a b" "b a"; ``` A useful consequence: the same name may appear many times, but only in a block. `"header header"` is one area two columns wide, not two areas that happen to share a name. ## Failure is silent and total An invalid `grid-template-areas` value is not partially applied. Per the usual CSS rule, the whole declaration is dropped, so the container ends up with no named areas — and every item whose only placement was `grid-area: <name>` now resolves that name against a line that does not exist, so the items fall back to automatic placement. The classic symptom is a page-shaped layout collapsing into one column after a small edit, and the cause is almost always a missing token or a name that stopped being rectangular. Browser devtools grid overlays name the areas they recognise, which is the fastest way to confirm the declaration was accepted at all. ## Rows and columns still have to exist `grid-template-areas` defines the *shape* of the explicit grid, but not the sizes. Track sizes come from `grid-template-columns` and `grid-template-rows`, and if the areas map declares more rows than the row template does, the remaining rows are still created — they simply take their size from the automatic row sizing rather than from your template. Writing the two side by side, with the same number of tokens per row as you have column tracks, keeps the picture honest. ## Why interviewers like this syntax It makes responsive restructuring cheap. A media query can rewrite the whole layout by replacing one declaration: ```css @media (width < 40rem) { .page { grid-template-columns: 1fr; grid-template-areas: "header" "main" "sidebar" "footer"; } } ``` No child rule changes, and the visual order can differ from the source order — which is exactly where an interviewer may probe: reordering regions this way does not reorder the DOM, so keyboard and screen-reader order still follows the markup, and a map that fights the source order is an accessibility problem, not just a styling choice. ## When not to use it Areas suit named, stable regions — page chrome, card internals, form sections. They suit repetitive grids badly: you cannot name a hundred cells, and a gallery of identical items wants automatic placement with a span where needed. Mixing the two in one container is fine, and common: name the structural regions, let the rest flow.

  • What happens to a child whose `grid-area` name does not appear in the container's `grid-template-areas`?
    The name resolves to no line, so the item is not placed by that rule and falls back to automatic placement, flowing into the next available cell. Nothing errors and nothing warns, which is why a typo in an area name shows up as one item mysteriously sitting in the wrong place rather than as a broken stylesheet.
  • Can you reorder regions responsively with `grid-template-areas` without touching the markup?
    Yes — a media query can replace the whole map, and the regions move. Be deliberate about it: the DOM order is unchanged, so tab order and screen-reader order still follow the source. A visual order that diverges far from the source order is an accessibility defect, so reorder regions only where the reading order still makes sense.
  • How do `grid-template-areas` and explicit track sizing work together?
    The areas map defines the shape — how many rows and columns the explicit grid has and which cells carry which name — while `grid-template-columns` and `grid-template-rows` size those tracks. Keep the token count per string equal to the number of column tracks; if the map declares more rows than the row template sizes, the extra rows are created and sized automatically.

saying these in an interview costs you the question

  • Thinks an L-shaped area is allowed
  • Says a dot reserves the cell against other items
  • Believes an invalid row is ignored while the rest applies
  • Thinks grid-template-areas also sets track sizes
  • Assumes reordering areas reorders the DOM for assistive tech

context