Drawing the layout
In the last lesson you built grids by counting columns and spanning tracks. For whole-page layouts there is a more readable way: draw the layout in your CSS as a map, and give each region a name.
<style>
.page {
display: grid;
grid-template-columns: 180px 1fr;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
min-height: 240px;
gap: 8px;
}
.page > * { padding: 12px; border-radius: 6px; }
header { grid-area: header; background: #fde68a; }
nav { grid-area: sidebar; background: #bfdbfe; }
main { grid-area: main; background: #bbf7d0; }
footer { grid-area: footer; background: #fecaca; }
</style>
<div class="page">
<header>Header</header>
<nav>Sidebar</nav>
<main>Main content</main>
<footer>Footer</footer>
</div>You can read the layout straight off the CSS: the header and footer stretch across both columns, with a sidebar and main content in the middle.
How it works
grid-template-areastakes one quoted string per row. Each word is a cell, and cells with the same name join into one region.grid-template-columnsandgrid-template-rowsset the sizes of the tracks the map describes. The map decides which region goes where; the track sizes decide how big.grid-area: nameon a child assigns it to a region.
Rules that matter:
- Every row must have the same number of cells.
- A named area must be a rectangle. A name appearing in an L or split shape makes the declaration invalid.
- A dot (
.) marks an empty cell:"header header .".
Why the HTML doesn't change
Notice that the HTML in the example is in a natural source order (header, nav, main, footer), and the CSS places things. That is the key benefit: the visual layout becomes a separate concern from the document order. Keep the source order logical for keyboard and screen reader users, and let the grid do the arranging. (Avoid wild differences between the two, since tabbing jumps around visually.)
Responsive layouts by redrawing the map
The best trick: on small screens, change the map and leave everything else alone. Media queries are covered in a later lesson; here is a preview.
<style>
.page {
display: grid;
gap: 8px;
grid-template-columns: 1fr;
grid-template-areas:
"header"
"main"
"sidebar"
"footer";
}
.page > * { padding: 12px; border-radius: 6px; }
header { grid-area: header; background: #fde68a; }
nav { grid-area: sidebar; background: #bfdbfe; }
main { grid-area: main; background: #bbf7d0; }
footer { grid-area: footer; background: #fecaca; }
@media (min-width: 600px) {
.page {
grid-template-columns: 160px 1fr;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
}
}
</style>
<div class="page">
<header>Header</header>
<nav>Sidebar</nav>
<main>Main content</main>
<footer>Footer</footer>
</div>On a narrow screen everything stacks, with the sidebar after the main content. At 600px and above it becomes the two-column layout. Resize the preview to see the change.
Named lines (a peek)
You can also name the lines between tracks, with grid-template-columns: [full-start] 1fr [content-start] minmax(0, 60ch) [content-end] 1fr [full-end];, and place items with grid-column: content-start / content-end. It is powerful for article layouts where images may break out of the text column, though areas are enough for most pages.
Alignment inside a grid
Grid has the same alignment ideas as Flexbox, with a few extras:
justify-itemsandalign-items: align items inside their cells.justify-contentandalign-content: align the whole grid inside its container if the tracks are smaller than the container.place-items: centeris shorthand for both, andplace-content: centercentres a grid's contents on both axes.justify-selfandalign-selfoverride alignment for a single item.
Common mistakes
- Rows with different numbers of cells in the map.
- A non-rectangular area, which silently voids the map.
- A typo in a name, so the element falls out of its region.
- Forgetting to set track sizes, leaving every track as
auto. - Changing the visual order drastically, creating a tab order that jumps around.
Exercise
Make a blog layout: a header across the top, an article on the left taking two thirds, an aside on the right taking one third, and a footer across the bottom.
Show one possible answer
<style>
.blog {
display: grid; gap: 10px;
grid-template-columns: 2fr 1fr;
grid-template-areas:
"head head"
"post side"
"foot foot";
}
.blog > * { padding: 12px; background: #e0e7ff; border-radius: 6px; }
.blog header { grid-area: head; }
.blog article { grid-area: post; }
.blog aside { grid-area: side; }
.blog footer { grid-area: foot; }
</style>
<div class="blog">
<header>Header</header>
<article>Article</article>
<aside>Aside</aside>
<footer>Footer</footer>
</div>Key points
- grid-template-areas draws the layout as rows of text, giving each region a name.
- Each element joins an area with grid-area and its name.
- Repeating a name across cells makes that area span them, and a dot leaves a cell empty.
- Redefining the map inside a media query rearranges the page without touching the HTML.
- Areas must form rectangles, and every row of the map needs the same number of cells.