---
title: "CSS Grid Areas Cheatsheet"
slug: "css-grid-areas"
category: "cheatsheets"
tags: ["cheatsheets", "css", "grid", "layout", "responsive", "frontend"]
status: "stable"
last_updated: 2026-05-14
summary: "CSS grid-template-areas syntax, area naming, placement rules, responsive overrides, and the common full-page layouts built with named areas."
related:
  [
    "[[frontend/css]]",
    "[[frontend/tailwind]]",
    "[[cheatsheets/css-selectors]]",
    "[[cheatsheets/css-units]]",
    "[[frontend/html]]",
    "[[frontend/react]]",
    "[[cheatsheets/index|Cheatsheets]]",
  ]
---

## Overview

`grid-template-areas` lets you assign human-readable names to grid regions and place items by name rather than by line numbers. This makes layout code self-documenting and easy to restructure at different breakpoints. This card covers the syntax, naming rules, alignment properties, and the canonical layouts that named areas enable. For utility-class grids in Tailwind see [[frontend/tailwind]].

## grid-template-areas syntax

Assign area names in the container; use `grid-area` on items.

```css
.layout {
  display: grid;
  grid-template-areas:
    "header header"
    "sidebar main"
    "footer footer";
  grid-template-columns: 240px 1fr;
  grid-template-rows: auto 1fr auto;
}

.header  { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main    { grid-area: main; }
.footer  { grid-area: footer; }
```

| Rule | Detail |
|---|---|
| Each string is one row | Strings separated by whitespace, each defines one row |
| Each word is one column | Words map left-to-right to columns in that row |
| Span by repeating the name | `"header header header"` spans 3 columns |
| Empty cell | Use `.` (a dot) for a cell not covered by any named area |
| Names must be valid idents | Letters, digits, `-`, `_`; no spaces in a single name |
| Rectangular shape required | A named area must form an unbroken rectangle |

## grid-template shorthand

`grid-template` combines rows, columns, and areas in one declaration.

```css
.layout {
  display: grid;
  grid-template:
    "header header" auto
    "sidebar main"  1fr
    "footer footer" auto
    / 240px 1fr;       /* column sizes after the slash */
}
```

| Shorthand | Equivalent |
|---|---|
| `grid-template: "a b" 100px / 1fr 2fr` | Rows + cols + areas |
| `grid: "a b" auto / 1fr 2fr` | `grid` also sets implicit tracks |
| `grid-area: header` | Name an item for placement |
| `grid-area: 2 / 1 / 4 / 3` | Explicit line-based placement (row-start/col-start/row-end/col-end) |

Avoid mixing named and line-based placement in the same layout. Pick one style and stick to it.

## Alignment and gaps

| Property | Values | Effect |
|---|---|---|
| `gap` | `<row-gap> <col-gap>` | Space between tracks; shorthand for `row-gap` + `column-gap` |
| `justify-items` | `start \| end \| center \| stretch` | Align items along the row axis within their cells |
| `align-items` | `start \| end \| center \| stretch` | Align items along the column axis |
| `place-items` | `<align-items> / <justify-items>` | Shorthand |
| `justify-content` | `start \| end \| center \| space-between \| space-around \| space-evenly` | Distribute columns when tracks don't fill container |
| `align-content` | same values | Distribute rows when tracks don't fill container |
| `place-content` | shorthand | Align and justify the whole grid |
| `justify-self` | same as `justify-items` | Per-item override for row axis |
| `align-self` | same as `align-items` | Per-item override for column axis |

## Responsive overrides

Redefine `grid-template-areas` inside a media query to change the layout. Item names stay the same.

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

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

/* Desktop */
@media (min-width: 1200px) {
  .layout {
    grid-template-areas:
      "header  header  header"
      "sidebar main    aside"
      "footer  footer  footer";
    grid-template-columns: 200px 1fr 200px;
  }
}
```

Items do not need to change at all; only the container's template changes.

## Common layouts

| Layout name | Template string |
|---|---|
| Holy grail | `"header" "sidebar main aside" "footer"` with 3 columns |
| Dashboard | `"nav nav" "sidebar content" / 60px 1fr` |
| Full-bleed header | `"header" "content" / 1fr` with header spanning full width |
| Card grid (auto-fill) | `repeat(auto-fill, minmax(280px, 1fr))` with no named areas |
| Sticky sidebar | `"sidebar main" / 280px 1fr` + `position: sticky` on sidebar |

For auto-fill card grids, prefer `grid-template-columns` alone without named areas; the implicit placement algorithm handles wrapping automatically.

## Common gotchas

- A named area must be a perfect rectangle. An L-shaped or T-shaped region (e.g., `"a b" "a a"`) is invalid and falls back to the initial value.
- `grid-area` on an item overrides all four placement lines at once. Setting it after individual `grid-row` or `grid-column` declarations discards those declarations.
- `gap` does not collapse. Adding `gap: 1rem` between a header and content that already have `margin-bottom` stacks both gaps.
- Items placed outside named areas (via line numbers or auto placement) can overlap named-area items without a `z-index`.
- `grid-template-areas` with a dot `.` cell does not prevent auto-placed items from filling that cell. Use `grid-column: span 1` and explicit placement to prevent it.
- The `fr` unit distributes free space after fixed tracks and gaps are subtracted. `1fr` in a container with `gap: 24px` is smaller than `1fr` in the same container without a gap.

## Related

- [[frontend/css]]
- [[frontend/tailwind]]
- [[cheatsheets/css-selectors]]
- [[cheatsheets/css-units]]
- [[frontend/html]]
- [[frontend/react]]
- [[cheatsheets/index|Cheatsheets]]
