Home / Blog / grid-template-areas: Build Complex Layouts with Named Grid Zones
CSS Grid 2026-09-23 · 9 min read

grid-template-areas: Build Complex Layouts with Named Grid Zones

Master grid-template-areas to create intuitive, visual CSS Grid layouts with named zones. Includes full page layout and responsive examples.

What Is grid-template-areas?

CSS Grid's grid-template-areas property is one of the most visually intuitive features in all of CSS. Instead of placing grid items with abstract line numbers, you draw your layout as an ASCII art diagram directly in your CSS. The browser reads this diagram and positions your elements accordingly.

This property is perfect for high-level page structure — the kind of layout you might sketch on a whiteboard. Think headers, sidebars, main content areas, and footers. With grid-template-areas, what you type in your CSS literally looks like what you see in the browser.

Basic Syntax

Each string in the property value represents one row of the grid. Each word within a string represents one cell, and cells with the same name form a single named area.

.container {
  display: grid;
  grid-template-areas:
    "header header header"
    "sidebar main main"
    "footer footer footer";
  grid-template-columns: 240px 1fr 1fr;
  grid-template-rows: 80px 1fr 60px;
}

This defines a three-column, three-row grid. The header area spans all three columns in the first row. The sidebar occupies the first column of the second row, while main spans the second and third columns. The footer spans all three columns in the last row.

The grid-area Property on Children

Naming areas in grid-template-areas is only half the work. You must also assign each child element to its named area using the grid-area property.

header  { grid-area: header; }
aside   { grid-area: sidebar; }
main    { grid-area: main; }
footer  { grid-area: footer; }

The value of grid-area must exactly match a name defined in grid-template-areas. Names are case-sensitive. The order of elements in your HTML does not affect placement — CSS Grid positions them purely by their grid-area assignment, which is a powerful advantage for accessibility and SEO (content order in HTML can differ from visual order).

Complete Full-Page Layout Example

Here is a complete, working example of the classic header–sidebar–main–footer layout often called the "Holy Grail" layout:

/* HTML Structure */
<div class="page">
  <header>Site Header</header>
  <nav>Sidebar Nav</nav>
  <main>Main Content</main>
  <aside>Right Panel</aside>
  <footer>Site Footer</footer>
</div>

/* CSS */
.page {
  display: grid;
  min-height: 100vh;
  grid-template-columns: 220px 1fr 200px;
  grid-template-rows: 70px 1fr 60px;
  grid-template-areas:
    "header  header  header"
    "nav     main    aside"
    "footer  footer  footer";
}

header { grid-area: header; background: #1e293b; color: #fff; }
nav    { grid-area: nav;    background: #f1f5f9; }
main   { grid-area: main;   padding: 24px; }
aside  { grid-area: aside;  background: #f8fafc; }
footer { grid-area: footer; background: #1e293b; color: #fff; }

You can paste this directly into the Live HTML/CSS Editor to see it rendered instantly. Notice how the CSS reads like a wireframe — anyone on your team can understand the layout at a glance, even without deep CSS knowledge.

The Dot Syntax for Empty Cells

Sometimes you want a cell in your grid to remain empty — no element should occupy it. Use a period (.) as a placeholder for an empty cell.

.layout {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  grid-template-areas:
    "logo  .      nav"
    "hero  hero   hero"
    "foot  foot   foot";
}

The period in "logo . nav" creates an empty cell between the logo and the navigation. You can use multiple consecutive periods (...) for clarity — the browser treats any number of consecutive dots as a single empty cell.

Rules for Named Areas

There are important constraints on how you define grid areas:

  • Rectangular only: Every named area must form a rectangle. L-shapes, T-shapes, and other non-rectangular configurations are invalid and will cause the entire grid-template-areas value to be ignored.
  • No gaps within a name: If you write "a . a", the two a cells are not connected — they are two separate areas with the same name, which is invalid.
  • Consistent column count: Every row string must have the same number of cells. Inconsistent counts will also invalidate the entire declaration.
  • Valid identifiers: Area names follow CSS custom identifier rules. They cannot start with a number and cannot be CSS keywords like none or auto.

Named Lines Are Created Automatically

A powerful hidden benefit of grid-template-areas is that it automatically creates named grid lines. For each area named foo, the browser implicitly creates lines named foo-start and foo-end on all four sides of that area.

.container {
  grid-template-areas:
    "header header"
    "sidebar main";
}

/* You can now use these implicit named lines: */
.some-element {
  grid-column: sidebar-start / main-end;
  grid-row: header-end / main-end;
}

This bidirectional relationship between grid-template-areas and named lines gives you two complementary ways to describe and reference your grid structure.

Responsive Template Areas with Media Queries

One of the best use cases for grid-template-areas is creating responsive layouts by simply redefining the area map at different breakpoints. The visual nature of the property makes the before-and-after immediately obvious.

/* Desktop: three-column layout */
.page {
  display: grid;
  grid-template-columns: 240px 1fr 200px;
  grid-template-rows: 70px 1fr 60px;
  grid-template-areas:
    "header header  header"
    "nav    main    aside"
    "footer footer  footer";
  min-height: 100vh;
}

/* Tablet: two-column, sidebar collapses right panel */
@media (max-width: 1024px) {
  .page {
    grid-template-columns: 220px 1fr;
    grid-template-areas:
      "header header"
      "nav    main"
      "footer footer";
  }
  aside { display: none; }
}

/* Mobile: single-column stack */
@media (max-width: 640px) {
  .page {
    grid-template-columns: 1fr;
    grid-template-rows: auto;
    grid-template-areas:
      "header"
      "main"
      "nav"
      "footer";
  }
}

Notice how on mobile, the nav (sidebar) is moved below main. This way, the main content appears first for mobile users — a critical consideration for UX and SEO — while the desktop layout keeps the sidebar on the left. The HTML order does not change, only the visual order does. Use the CSS Formatter to keep your media query blocks clean and readable.

Dashboard Layout Example

.dashboard {
  display: grid;
  height: 100vh;
  grid-template-columns: 260px 1fr;
  grid-template-rows: 64px 1fr 50px;
  grid-template-areas:
    "sidebar  topbar"
    "sidebar  content"
    "sidebar  statusbar";
}

.sidebar    { grid-area: sidebar;    overflow-y: auto; }
.topbar     { grid-area: topbar; }
.content    { grid-area: content;    overflow-y: auto; padding: 20px; }
.statusbar  { grid-area: statusbar; }

This dashboard keeps the sidebar spanning the full height while the right side has a topbar, scrollable content area, and a status bar at the bottom. The grid-template-areas map makes this relationship completely explicit.

Combining with grid-template Shorthand

The grid-template shorthand combines grid-template-rows, grid-template-columns, and grid-template-areas in one declaration:

.page {
  display: grid;
  grid-template:
    "header header" 70px
    "nav    main"   1fr
    "footer footer" 60px
    / 240px 1fr;
}

Each row is written as "area-names" row-height, and the column sizes follow a slash at the end. This is very compact but can be harder to read in complex layouts. Use it when brevity matters, and the expanded form when readability is the priority.

Best Practices

  • Use grid-template-areas for page-level layouts (header, nav, main, footer). For component-level grids with many similar items (card grids, galleries), use repeat() and auto-fill/auto-fit instead.
  • Keep names semantic: Use header, sidebar, main, footer rather than abstract names like a, b, c.
  • Always pair grid-template-areas with explicit grid-template-columns and grid-template-rows to avoid relying on implicit track sizing.
  • When reordering areas in media queries for accessibility, ensure the logical reading order is maintained in the HTML.

Frequently Asked Questions

Can a named area span multiple rows and columns?
Yes. Simply repeat the area name in consecutive cells across rows and/or columns. For example, "sidebar main" / "sidebar footer" makes sidebar span two rows. The area must always be rectangular — it cannot be an L-shape or have gaps within it.
What happens if a grid-area name doesn't match any template area?
The element with the unmatched grid-area name is placed in the implicit grid — the browser auto-places it after all explicitly placed items. This is usually unintentional, so always double-check for typos between your grid-template-areas names and grid-area values.
Is grid-template-areas supported in all browsers?
Yes. grid-template-areas has full support in all modern browsers including Chrome, Firefox, Safari, and Edge. It has been widely supported since 2017 and has no meaningful browser compatibility issues for current web projects.
Can I use grid-template-areas without specifying column/row sizes?
Yes, but the tracks will use implicit sizing (auto). It is best practice to always pair grid-template-areas with grid-template-columns and grid-template-rows for predictable, intentional layout behavior.
How do I make an element span the full width using grid-template-areas?
Simply repeat the area's name across all columns in that row. For a 3-column grid, "header header header" makes the header span all three columns. This is equivalent to setting grid-column: 1 / -1 on the element.

Try Our Free HTML CSS Tools

Build and visualize your CSS Grid layouts with our free online tools.

Live HTML/CSS Editor CSS Formatter CSS Minifier