Topic 8.4
Template Areas
In one line
grid-template-areas lets you draw a layout as text, one quoted string per row and one name per cell; each item then joins its area with grid-area: name, and changing the drawing in a media query rearranges the whole page.
Think of it like this
Planning a garden on squared paper. You write a letter in each square: T for tomatoes, F for flowers, a dot for an empty square. All the T squares together make the tomato bed. You can see the whole garden at a glance, and to move the flowers you rewrite a few letters instead of measuring anything. grid-template-areas is that squared paper.
Words you'll meet
New words in this topic, in plain English. Come back here whenever one feels fuzzy.
- `grid-template-areas`
- A property where you draw the layout as quoted strings, one per row, with a name in each cell.
- Area name
- A word you invent, like
header, written in the cells an area should cover. - `grid-area: name`
- Put on an item to place it into the area with that name.
- Empty cell
- A cell marked with a dot
., where no named area goes. - Rectangle rule
- Every named area must form one solid rectangle, or the whole drawing is ignored.
- `grid-template`
- A shorthand that sets areas, row sizes and column sizes in one declaration.
- Implicit named lines
- The lines
name-startandname-endthat every named area creates automatically.
Step by step
01Sketch the layout
On paper, a classic page: a header across the top, a sidebar and main content side by side, a footer across the bottom. That's 3 rows and 2 columns.
02Write the sketch as strings
One string per row, one name per column. The strings line up like the picture.
.page {
display: grid;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
}03Give the tracks sizes
The areas only name the cells. Add a 200px sidebar column and a flexible main column, and let the middle row take the remaining height.
.page {
display: grid;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
grid-template-columns: 200px 1fr;
grid-template-rows: auto 1fr auto;
min-height: 100vh;
gap: 16px;
}04Put each item in its area
Each child says which area it belongs to. The order of the children in the HTML no longer decides where they go.
.page > header { grid-area: header; }
.page > nav { grid-area: sidebar; }
.page > main { grid-area: main; }
.page > footer { grid-area: footer; }05Leave a cell empty
Want the footer only under the main content? Put a dot in the sidebar column of the last row. The dot is one empty cell.
grid-template-areas:
"header header"
"sidebar main"
". footer";06Redraw it for phones
Write the one-column drawing first (mobile first), then redraw it for wide screens. Only the strings and track sizes change.
.page {
display: grid;
grid-template-areas: "header" "main" "sidebar" "footer";
}
@media (min-width: 700px) {
.page {
grid-template-columns: 200px 1fr;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
}
}Try it yourself
- 1
Move the sidebar to the right
In the first example, change only the strings so the sidebar is on the right, and swap the column sizes to
1fr 100px. Predict the newxvalues fornavandmain(main at 0, nav at 300), then run. - 2
Add an empty cell
In the first example, change the last row to
". footer". Predict the footer'sxand width (108 and 292). Run and check. - 3
Fix the typo
In the second example, add a second row to
.okso areacexists:grid-template-areas: "a b" "c c";. Predict where the red item goes now (x=0 y=40, across both columns).
Code & diagrams
The computed value prints the drawing back as strings. Each item filled the rectangle its name covers: the header and footer are the full 400px wide.
Preview
Console
Nothing logged yet.Expected console output
"header header" "sidebar main" "footer footer"
header x=0 y=0 400x40
nav x=0 y=48 100x100
main x=108 y=48 292x100
footer x=0 y=156 400x30Both broken drawings compute to `none`: the whole declaration is dropped. The item asking for a missing area `c` isn't hidden; it lands in implicit tracks beyond the end of the explicit grid, below and to the right of everything else.
Preview
Console
Nothing logged yet.Expected console output
.ok "a b"
.l-shape none
.uneven none
typo item at x=250 y=70Make the preview narrower and wider (or open it full screen): under 500px everything stacks; above it the aside moves beside the main content. The HTML never changes, and it stays in reading order.
Preview
Console
Nothing logged yet.Break it on purpose
Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.
Break #1
Draw an L-shaped area
Write grid-template-areas: "nav main" "nav nav"; to make the nav wrap under the main content.
Break #2
Quote the name on the item
Write grid-area: "header"; on the header element.
Myth vs fact
Myth
Area names must match class names or element names.
Fact
They're independent identifiers you invent. Matching them is only a readability habit.
Myth
... is three empty cells.
Fact
A run of dots with no spaces between them is one empty cell. Write . . . (with spaces) for three.
Myth
Rearranging areas is a safe way to change the order of content.
Fact
It changes only the visual order. Screen readers and Tab follow the HTML, so a big difference between the two confuses people. Keep the HTML in a logical order.
Pro corner
Extra depth for experienced readers. New to this? Skip it for now and come back later.
- ▸
Rows in
grid-template-areaswith different cell counts, non-rectangular areas, or an area split in two make the value invalid at parse time, which is why it computes tononerather than a partly working layout. - ▸
If the area strings have more columns than
grid-template-columns, the extra columns become implicit tracks sized bygrid-auto-columns. The explicit grid is the larger of the two in each direction. - ▸
A missing area name on an item resolves its lines as implicit named lines after the explicit grid, so the item ends up in implicit tracks beyond the explicit grid instead of disappearing. In DevTools, the grid overlay's Show area names option makes such typos obvious.
- ▸
grid-templateandgridare shorthands that reset the properties they don't mention (gridalso resetsgrid-auto-*). Writinggrid-template-areasafter them is fine, but writinggrid-template: …aftergrid-template-areaswipes the areas.
Remember this
- 1
grid-template-areastakes one quoted string per row. Inside each string, write one name per column, separated by spaces. Repeating a name across neighbouring cells makes that area bigger:"header header" "sidebar main" "footer footer"is three rows and two columns, with the header and footer stretched across both columns. Put each string on its own line so the code looks like the layout. - 2
Each item joins an area with **
grid-area: name** (no quotes):.site-header { grid-area: header; }. The item fills the whole rectangle covered by that name. The names are yours to choose, like custom class names; they must not start with a digit, and they don't need to match class names, though matching them keeps things readable. - 3
A dot
.marks an empty cell that no area uses. Several dots written together without spaces (...) still count as one cell, which helps line up the columns of your drawing. Areas must be rectangles: an L shape, a name used in two separate places, or rows with different numbers of cells make the whole declaration invalid, so it is dropped and nothing is placed by name. - 4
grid-template-areasonly names cells; the sizes still come fromgrid-template-columnsandgrid-template-rows. The number of columns in your strings should match the column template; if they differ, the browser adds implicit tracks to make them agree. The **grid-template** shorthand writes all three together, with each row size after its string and the columns after a slash:grid-template: "head head" 60px "side main" 1fr / 200px 1fr;. - 5
Every named area also creates named lines for free: an area called
maingives you linesmain-startandmain-endin both directions. So an item can saygrid-column: main-start / main-end, or another item can overlap the area withgrid-area: main. The reverse works too: lines you namedcontent-startandcontent-endcreate an implicit area calledcontent. - 6
Areas make responsive layouts short and clear. On phones, draw one column:
"header" "main" "sidebar" "footer". Inside a media query (Phase 9) for wider screens, redraw it with the sidebar beside the main content. The HTML and the items'grid-areanames never change. Remember that moving areas changes only the visual order: keyboard focus and screen readers still follow the HTML, so keep the source order sensible.
Explain it without notes
How does grid-template-areas work, and how does an item join an area?
What makes a grid-template-areas value invalid, and what happens then?
How would you make a layout that is one column on phones and has a sidebar on desktops, using areas?
What named lines does an area create, and how can you use them?
Practice
Draw a dashboard: a header across the top; below it a narrow menu on the left and two equal panels side by side on the right; no footer.
Write a grid-template shorthand for a 2-column layout with rows header (60px), side main (1fr) and foot foot (40px), and columns 180px 1fr.
A card has an image, a title and text. Use areas so the image is on the left spanning both rows, the title top-right and the text bottom-right.
Trade-offs
- ↔
Areas read like a picture and make responsive rearranging trivial, but every cell must be named or dotted, so very big or irregular grids are clearer with line numbers or spans.
- ↔
Large visual reordering with areas is easy to write and easy to get wrong for accessibility; keep visual order and source order close.
Done when you can
I can draw a layout with
grid-template-areasand place items withgrid-area: name.I can leave cells empty with
.and keep areas rectangular.I can use the
grid-templateshorthand.I can rearrange a layout for different screen widths by redrawing the areas.
I can use the
-start/-endlines an area creates.