Problem Solved

CSS · grid-template-areas

Home › Courses › CSS › Problems › Grid template areas
🎨 Concept · 3 min read

grid-template-areas.
Readable grid layouts.

The most readable grid technique in CSS. Instead of counting columns and rows, you draw the layout with strings: 'header header' 'sidebar main' 'footer footer'. Then you assign elements to named regions with grid-area. The CSS looks like the layout it produces. This page covers the syntax, the dot-for-empty-cell trick, and the responsive pattern that makes it worth learning.

Short answer: Define named regions on the grid container with grid-template-areas — each row is a string, each name is a cell, repeated names merge. Assign children to regions with grid-area: name. Use . for empty cells. Redefine the template at a media query to change the layout responsively — the children don't change, only the template. This is the most readable way to write page layouts in CSS grid.

✅ The basic pattern

Draw the layout with strings.

grid-areas.css
.layout {
  display: grid;
  grid-template-columns: 240px 1fr;
  grid-template-rows: 64px 1fr 80px;
  grid-template-areas:
    "header header"
    "sidebar main"
    "footer footer";
  gap: 1rem;
  min-height: 100vh;
}

.header { grid-area: header; background: #2965f1; }
.sidebar { grid-area: sidebar; background: #64748b; }
.main { grid-area: main; background: #f1f5f9; color: #1e293b; }
.footer { grid-area: footer; background: #334155; }
Visual layout:

┌──────────────────────────────┐
│ header                       │ 64px
├──────────┬───────────────────┤
│          │                   │
│ sidebar  │ main              │ 1fr
│ 240px    │ auto              │
│          │                   │
├──────────┴───────────────────┤
│ footer                       │ 80px
└──────────────────────────────┘

Read the CSS at the top:
"header header" → header spans 2 columns
"sidebar main" → sidebar + main side by side
"footer footer" → footer spans 2 columns

The CSS matches the layout visually.
No counting columns. No grid-column: 1 / 3.
Just names.

✅ Easy to read.
✅ Easy to modify — change the strings.
✅ Easy to make responsive — redefine at a media query.

✅ Responsive — the big win

Redefine the template. Children don't change.

responsive-areas.css
.layout {
  display: grid;
  gap: 1rem;
  grid-template-columns: 1fr;
  grid-template-areas:
    "header"
    "main"
    "sidebar"
    "footer";
}

@media (min-width: 768px) {
  .layout {
    grid-template-columns: 240px 1fr;
    grid-template-areas:
      "header header"
      "sidebar main"
      "footer footer";
  }
}
Mobile (< 768px):

┌───────────────────┐
│ header            │
├───────────────────┤
│ main              │
├───────────────────┤
│ sidebar           │
├───────────────────┤
│ footer            │
└───────────────────┘

Desktop (≥ 768px):

┌──────────────────────────────┐
│ header                       │
├──────────┬───────────────────┤
│ sidebar  │ main              │
├──────────┴───────────────────┤
│ footer                       │
└──────────────────────────────┘

✅ Sidebar moves below main on mobile.
✅ Header and footer span full width on desktop.
✅ One template per breakpoint.
✅ .sidebar, .main etc. never change — their
grid-area is the same name everywhere.

This is the cleanest responsive grid technique.
Change the strings, everything follows.

✅ Empty cells and spans

Use dots for gaps.

dots-and-spans.css
.page {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-template-areas:
    "hero hero hero hero"
    "promo . sidebar sidebar"
    "footer footer footer footer";
  gap: 1rem;
}

.hero { grid-area: hero; background: #2965f1; }
.promo { grid-area: promo; background: #f59e0b; }
.sidebar { grid-area: sidebar; background: #10b981; }
.footer { grid-area: footer; background: #334155; }
Visual layout:

┌──────────────────────────────────┐
│ hero                             │
├──────────┬─────┬─────────────────┤
│ promo    │ .   │ sidebar         │
├──────────┴─────┴─────────────────┤
│ footer                           │
└──────────────────────────────────┘

.promo occupies column 1 of row 2.
. (dot) marks the empty cell in column 2.
.sidebar spans columns 3-4 of row 2.

✅ hero spans all 4 columns.
✅ promo is 1 column.
✅ Dot creates the gap.
✅ sidebar is 2 columns.
✅ footer spans all 4.

The dot is how you leave space in a named grid.
Without it, the grid would fill every cell.

Rule: one dot = one empty cell. Repeat as needed.
Multiple dots (.... ) is convention for readability
but only one is required.

Don't use grid-template-areas without also defining grid-template-columns. The template areas define the shape of the grid, but the columns need explicit widths. Without grid-template-columns, the grid defaults to one auto-sized column per cell — which may be what you want, but usually isn't. Combine them: grid-template-columns: 240px 1fr sets the widths, grid-template-areas sets the layout. Both are needed. If you only set grid-template-areas, the grid still works, but the columns are sized by content, not by your design.

⚠️ Common mistakes

The grid-template-areas mistakes that cost real time.

1. Uneven row lengths

'header header' and 'sidebar' — different cell counts. Fix: every row must have the same number of cells.

2. Name mismatch

grid-area: Header vs template 'header'. Case-sensitive. Fix: match exactly.

3. grid-area on non-grid children

Only direct children of the grid container accept grid-area. Fix: move the element or use a nested grid.

4. Forgetting grid-template-columns

The grid uses auto-sized columns. Fix: define column widths explicitly.

5. Spaces inside the area name

grid-area: 'my header' — invalid. Fix: no spaces in area names.

6. Using a name that's not in the template

The element becomes auto-placed. Fix: ensure the name is in the template strings.

7. Forgetting the row count

grid-template-rows defaults to auto — usually fine, but explicit rows help with fixed heights.

8. Overcomplicated templates

A 6×6 template for a simple layout. Fix: only name the regions you need; use grid-column/row for the rest.

❓ Frequently asked

What is grid-template-areas?

grid-template-areas is a CSS grid property that lets you name regions of a grid using an ASCII-art string. Each string is a row, each name in the string is a cell, and repeated names merge into a single region. Example: grid-template-areas: 'header header' 'sidebar main' 'footer footer'. Then .header { grid-area: header; } places the element in that region.

How does grid-area work with template areas?

grid-area: places a child element into the named region defined by grid-template-areas. The name must match exactly (case-sensitive). One grid-area can span multiple cells if that name appears multiple times in the template. For example, grid-template-areas: 'header header' 'sidebar main' with .header { grid-area: header } — the header element occupies both columns of the first row.

Can I have empty cells in grid-template-areas?

Yes — use a dot (.) for an empty cell. grid-template-areas: 'header header' 'sidebar .' 'footer footer' — the middle-right cell is empty. Use multiple dots (...) for wider gaps. Empty cells let you create L-shaped regions and gaps within a grid. The dot is not a name — it means 'no grid-area here'.

Can grid-template-areas be responsive?

Yes — this is where it shines. Redefine the whole grid at a media query by changing the strings: grid-template-areas: 'header' 'main' 'sidebar' 'footer' on mobile, then 'header header' 'sidebar main' 'footer footer' on desktop. The child elements don't change — they keep grid-area: header, grid-area: sidebar, etc. Only the template strings change.

Why doesn't my grid-area work?

Four common causes. (1) The name doesn't match — 'Header' vs 'header', case-sensitive. (2) The grid container doesn't have grid-template-areas defined. (3) The element is not a direct child of the grid. (4) The template strings have different lengths. Fix each at the source.

When should I use grid-template-areas vs grid-column/grid-row?

Use grid-template-areas when the layout has named, rectangular regions — page layouts, dashboards, card grids with featured items. Use grid-column/grid-row when the layout is more dynamic or irregular — when cells have complex spans, when the grid is auto-generated. For most page-level layouts, grid-template-areas is the better tool.

🔗 Related

← All CSS problems
Problem solved · CSS