Skip to main content

Grid Template Areas: Visual Layout Design

grid-template-areas is the most intuitive and visually expressive way to design page layouts. It lets you name regions of the grid and arrange them using an ASCII-art-like map in your CSS.

1. How It Works

  1. Give each grid item a name with grid-area.
  2. Map the visual layout using strings in grid-template-areas.
  3. Control column widths and row heights with grid-template-columns / rows.
/* Step 1: Name the items */
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
.aside { grid-area: aside; }
.footer { grid-area: footer; }

/* Step 2: Map the layout */
.page {
display: grid;
grid-template-columns: 240px 1fr 200px;
grid-template-rows: 60px 1fr 60px;
grid-template-areas:
"header header header"
"sidebar main aside"
"footer footer footer";
min-height: 100vh;
gap: 1rem;
}
Visual representation of the above:
┌──────────────────────────────────┐
│ HEADER (3 cols) │ 60px
├──────────┬───────────┬───────────┤
│ │ │ │
│ SIDEBAR │ MAIN │ ASIDE │ 1fr
│ (240px) │ (1fr) │ (200px) │
│ │ │ │
├──────────┴───────────┴───────────┤
│ FOOTER (3 cols) │ 60px
└──────────────────────────────────┘

2. Empty Cells: The Period .

Use a . or multiple ... to create an intentionally empty cell:

.container {
display: grid;
grid-template-columns: 1fr 2fr 1fr;
grid-template-areas:
"logo nav actions"
". hero ." /* Left + right cells are empty */
"sidebar content .";
}

3. Spanning: Repeat the Name

A grid area spans multiple cells by repeating the name across those cells:

grid-template-areas:
"header header header" /* header spans all 3 columns */
"sidebar main main" /* main spans 2 columns */
"footer footer footer"; /* footer spans all 3 columns */

[!IMPORTANT] Named areas must form a complete rectangle. You cannot make an L-shaped or irregular area. If you try, the CSS is invalid and the grid is ignored.

4. Responsive Named Areas (Media Query Pattern)

The power of named areas: completely rearrange your layout just by changing the area map on different screen sizes.

/* Mobile: single column */
.page {
display: grid;
grid-template-columns: 1fr;
grid-template-areas:
"header"
"main"
"sidebar"
"footer";
}

/* Tablet: 2 columns */
@media (min-width: 768px) {
.page {
grid-template-columns: 220px 1fr;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
}
}

/* Desktop: 3 columns */
@media (min-width: 1024px) {
.page {
grid-template-columns: 220px 1fr 180px;
grid-template-rows: 70px 1fr 60px;
grid-template-areas:
"header header header"
"sidebar main aside"
"footer footer footer";
}
}

5. grid-template Shorthand

Combines grid-template-rows, grid-template-columns, and grid-template-areas:

/* grid-template: rows / columns */
.page {
display: grid;
grid-template:
"header header" 70px
"sidebar main" 1fr
"footer footer" 60px
/ 220px 1fr; /* column widths */
}

6. Dashboard Layout — Real World Example

.dashboard {
display: grid;
grid-template-columns: 80px 1fr 320px;
grid-template-rows: 60px 1fr;
grid-template-areas:
"sidebar topbar topbar"
"sidebar content panel";
height: 100vh;
}

.sidebar { grid-area: sidebar; background: #111; }
.topbar { grid-area: topbar; background: #1c1c1e; }
.content { grid-area: content; padding: 2rem; overflow-y: auto; }
.panel { grid-area: panel; background: #1c1c1e; border-left: 1px solid rgba(255,255,255,0.06); }

7. Blog Layout — Real World Example

.blog {
display: grid;
gap: 2rem;
grid-template-columns: 1fr 280px;
grid-template-areas:
"header header"
"posts sidebar"
"footer footer";
max-width: 1200px;
margin: 0 auto;
padding: 0 1.5rem;
}

.blog-header { grid-area: header; }
.blog-posts { grid-area: posts; }
.blog-sidebar { grid-area: sidebar; }
.blog-footer { grid-area: footer; }

@media (max-width: 768px) {
.blog {
grid-template-columns: 1fr;
grid-template-areas:
"header"
"posts"
"sidebar"
"footer";
}
}

8. Naming Conventions for Grid Areas

  • Use descriptive, semantic names: header, sidebar, main, footer, panel, hero.
  • Avoid abbreviations like h, s, m — they become unreadable in complex layouts.
  • Use BEM-style names for component-level grids: card__image, card__body.