CSS course menu
CSS Grid Lines and grid-template-areas: Placing Items and Page Layouts
Place CSS grid items precisely with grid lines (grid-column, grid-row, negative line numbers), name regions with grid-template-areas to build page layouts, change layouts with media queries, and line up nested content with subgrid.
On this page
In the CSS Grid lesson, items flowed into cells automatically. You can also put items in exact positions, either by line numbers or by naming areas of the grid.
Grid lines#
Grid lines are the lines between tracks, numbered from 1. A 3-column grid has 4 vertical lines:
line: 1 2 3 4
| col 1 | col 2 | col 3 |grid-column: start / end places an item between two lines:
.grid { display: grid; grid-template-columns: repeat(3, 1fr); grid-auto-rows: 50px; gap: 6px; }
.grid div { background: #2f5fe0; color: white; padding: 6px; font: 13px monospace; }
.a { grid-column: 1 / 3; } /* lines 1 to 3: two columns */
.b { grid-column: 3; grid-row: 1 / 3; }
.c { grid-column: 1 / -1; } /* -1 is the last line: full width */<div class="grid">
<div class="a">grid-column: 1 / 3</div>
<div class="b">col 3, rows 1 / 3</div>
<div>auto</div>
<div>auto</div>
<div class="c">grid-column: 1 / -1</div>
</div>- Negative numbers count from the end:
-1is the last line, so1 / -1always spans the full width. span n(from the previous lesson) can be combined with a line:grid-column: 2 / span 2.
grid-template-areas#
For page layouts, naming areas is often clearer. Draw the layout as text, with one string per row:
.page {
display: grid;
grid-template-columns: 160px 1fr;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
gap: 8px;
min-height: 260px;
font-family: system-ui, sans-serif;
}
.page > * { padding: 10px; border-radius: 6px; color: white; }
header { grid-area: header; background: #1d3b4f; }
aside { grid-area: sidebar; background: #0f8a7e; }
main { grid-area: main; background: #2f5fe0; }
footer { grid-area: footer; background: #555; }<div class="page">
<header>Header</header>
<aside>Sidebar</aside>
<main>Main content</main>
<footer>Footer</footer>
</div>- Each string is a row; each word is a cell. A name repeated across cells makes the area span them.
- Areas must be rectangles.
- A
.marks an empty cell:"header .". - Each item is assigned with
grid-area: name.
Changing layout at different sizes#
Because the layout is a picture in one property, a media query can redraw it. Here the sidebar moves below the main content on narrow screens:
.page {
grid-template-columns: 1fr;
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";
}
}The HTML order stays the same, so keyboard and screen reader order stays logical. Only rearrange visually when the reading order still makes sense. Media queries are explained in Media Queries.
subgrid#
Normally a grid item's own children do not line up with the outer grid. grid-template-rows: subgrid (or columns) lets a nested grid reuse its parent's tracks, so headings, text and buttons line up across cards:
.cards {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 10px;
}
.card {
display: grid;
grid-row: span 3;
grid-template-rows: subgrid;
gap: 4px;
padding: 10px;
border: 1px solid #ccc;
border-radius: 8px;
}
.card h3, .card p { margin: 0; }<div class="cards">
<article class="card"><h3>Short</h3><p>One line.</p><a href="#">Buy</a></article>
<article class="card"><h3>A much longer heading that wraps</h3><p>Text.</p><a href="#">Buy</a></article>
<article class="card"><h3>Medium title</h3><p>A longer description that takes a few more lines to finish.</p><a href="#">Buy</a></article>
</div>The headings, paragraphs and links line up across all three cards, because they share the same three rows. Subgrid is supported in current versions of all major browsers.
Practice#
Practice exercise
Build a dashboard with grid-template-areas: a full-width "top" bar, then three columns where "nav" is on the left, "stats" in the middle and "alerts" on the right, and a "chart" area under stats and alerts spanning both of those columns.
Show solution
.dash {
display: grid;
grid-template-columns: 120px 1fr 1fr;
grid-template-areas:
"top top top"
"nav stats alerts"
"nav chart chart";
gap: 6px;
min-height: 220px;
}
.dash > div { padding: 8px; background: #eef3ff; border: 1px solid #c5d4fb; border-radius: 6px; }
.top { grid-area: top; }
.nav { grid-area: nav; }
.stats { grid-area: stats; }
.alerts { grid-area: alerts; }
.chart { grid-area: chart; }<div class="dash">
<div class="top">Top bar</div>
<div class="nav">Nav</div>
<div class="stats">Stats</div>
<div class="alerts">Alerts</div>
<div class="chart">Chart</div>
</div>Key takeaway#
Finished this lesson?