Skip to content

Grid Template Areas: A Semantic Approach to Layout Definition โ€‹

Imagine you're drawing a floor plan for a building. You wouldn't say "This is the area from line 1 to line 3, from line 2 to line 5," but rather you'd directly label "living room," "kitchen," "bedroom." Grid Template Areas follow this same approachโ€”using intuitive names rather than abstract numbers to define layouts.

In previous chapters, we learned how to position elements using grid line numbers. This method is precise, but code can become difficult to understand as layouts grow complex. Grid Template Areas provide a more intuitive and semantic way to define layouts, making your code read like a visual layout diagram.

Template Area Basics โ€‹

grid-template-areas: Defining the Layout Template โ€‹

The grid-template-areas property allows you to plan grid layouts using names. Each string represents a row, and names represent cells.

Let's start with a simple example:

css
.container {
  display: grid;
  grid-template-columns: 200px 1fr 200px;
  grid-template-rows: auto 1fr auto;
  min-height: 100vh;
  grid-template-areas:
    "header  header  header"
    "sidebar main    aside"
    "footer  footer  footer";
}

This code creates a 3ร—3 grid and names each area:

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ header โ”‚ header โ”‚ header โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚sidebar โ”‚  main  โ”‚  aside โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ footer โ”‚ footer โ”‚ footer โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

See how clear this layout is at a glance:

  • First row: header spans all three columns
  • Second row: sidebar, main, and aside each occupy one column
  • Third row: footer spans all three columns

grid-area: Assigning Items to Areas โ€‹

Once you've defined the template, use grid-area to assign items to their respective areas:

html
<div class="container">
  <header>Header</header>
  <nav>Sidebar</nav>
  <main>Main Content</main>
  <aside>Aside</aside>
  <footer>Footer</footer>
</div>
css
.container {
  display: grid;
  grid-template-columns: 200px 1fr 200px;
  grid-template-rows: auto 1fr auto;
  min-height: 100vh;
  gap: 10px;
  grid-template-areas:
    "header  header  header"
    "sidebar main    aside"
    "footer  footer  footer";
}

header {
  grid-area: header;
  background-color: #333;
  color: white;
  padding: 20px;
}

nav {
  grid-area: sidebar;
  background-color: #f5f5f5;
  padding: 20px;
}

main {
  grid-area: main;
  background-color: white;
  padding: 20px;
}

aside {
  grid-area: aside;
  background-color: #e3f2fd;
  padding: 20px;
}

footer {
  grid-area: footer;
  background-color: #333;
  color: white;
  padding: 20px;
}

Now each element clearly indicates its role in the layout. No need to remember grid line numbersโ€”the code is intuitive and easy to understand.

Empty Cells โ€‹

If a cell doesn't need any content, use a period (.) to represent it:

css
.grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(3, 100px);
  gap: 10px;
  grid-template-areas:
    "header header  header"
    "content content ."
    "footer  footer  footer";
}

In this example, the third cell in the second row is empty (represented by .).

You can use multiple periods to represent consecutive empty cells:

css
.grid {
  grid-template-areas:
    "header header  header"
    "content content ......"
    "footer  footer  footer";
}

While multiple periods have the same effect as one period, using multiple periods can improve visual alignment.

Naming Rules and Best Practices โ€‹

Naming Rules โ€‹

  1. Area names must be valid identifiers: Can contain letters, numbers, underscores, and hyphens, but cannot start with a number
  2. Area names are case-sensitive: Header and header are different areas
  3. Same areas must form rectangles: Cannot be L-shaped or other irregular shapes
css
/* โœ… Correct: header is a rectangle */
.grid {
  grid-template-areas:
    "header header"
    "main   aside";
}

/* โŒ Incorrect: header is L-shaped */
.grid {
  grid-template-areas:
    "header main"
    "header aside";
  /* This will cause an error! */
}

Best Practices โ€‹

1. Use Descriptive Names โ€‹

css
/* โœ… Good naming */
.grid {
  grid-template-areas:
    "site-header site-header site-header"
    "navigation main-content sidebar"
    "site-footer site-footer site-footer";
}

/* โŒ Poor naming */
.grid {
  grid-template-areas:
    "a a a"
    "b c d"
    "e e e";
}

2. Maintain Alignment for Readability โ€‹

css
/* โœ… Good alignment */
.grid {
  grid-template-areas:
    "header  header  header"
    "sidebar content aside"
    "footer  footer  footer";
}

/* โŒ Hard to read */
.grid {
  grid-template-areas:
    "header header header"
    "sidebar content aside"
    "footer footer footer";
}

Use consistent spacing to align each column visually, just like looking at an actual layout diagram.

3. Work with Semantic HTML Tags โ€‹

html
<div class="page-layout">
  <header>...</header>
  <!-- grid-area: header -->
  <nav>...</nav>
  <!-- grid-area: navigation -->
  <main>...</main>
  <!-- grid-area: content -->
  <aside>...</aside>
  <!-- grid-area: sidebar -->
  <footer>...</footer>
  <!-- grid-area: footer -->
</div>

Using semantic HTML tags with corresponding area names makes the code structure clear at a glance.

Complex Layout Examples โ€‹

Blog Layout โ€‹

Let's create a professional blog layout:

html
<div class="blog-layout">
  <header class="site-header">
    <h1>My Blog</h1>
  </header>
  <nav class="main-nav">Navigation</nav>
  <article class="post">
    <h2>Article Title</h2>
    <p>Article content...</p>
  </article>
  <aside class="sidebar">
    <h3>About</h3>
    <p>Sidebar content...</p>
  </aside>
  <aside class="widgets">
    <h3>Popular Posts</h3>
    <ul>
      <li>Post 1</li>
      <li>Post 2</li>
    </ul>
  </aside>
  <footer class="site-footer">
    <p>&copy; 2025 My Blog</p>
  </footer>
</div>
css
.blog-layout {
  display: grid;
  grid-template-columns: 200px 1fr 300px;
  grid-template-rows: auto auto 1fr auto;
  min-height: 100vh;
  gap: 20px;
  padding: 20px;
  grid-template-areas:
    "header  header  header"
    "nav     nav     nav"
    "sidebar post    widgets"
    "footer  footer  footer";
}

.site-header {
  grid-area: header;
  background-color: #2196f3;
  color: white;
  padding: 30px;
  text-align: center;
  border-radius: 8px;
}

.main-nav {
  grid-area: nav;
  background-color: #333;
  color: white;
  padding: 15px;
  border-radius: 8px;
}

.post {
  grid-area: post;
  background-color: white;
  padding: 30px;
  border: 1px solid #ddd;
  border-radius: 8px;
}

.sidebar {
  grid-area: sidebar;
  background-color: #f5f5f5;
  padding: 20px;
  border-radius: 8px;
}

.widgets {
  grid-area: widgets;
  background-color: #e3f2fd;
  padding: 20px;
  border-radius: 8px;
}

.site-footer {
  grid-area: footer;
  background-color: #333;
  color: white;
  padding: 20px;
  text-align: center;
  border-radius: 8px;
}

This layout clearly shows the positional relationships between different sections, making it easy to maintain the code.

Dashboard Layout โ€‹

Template areas are particularly useful when creating complex dashboards:

html
<div class="dashboard">
  <header class="dash-header">Dashboard</header>
  <nav class="dash-sidebar">Sidebar</nav>
  <div class="stats">Statistics</div>
  <div class="chart-main">Main Chart</div>
  <div class="chart-sub">Sub Chart</div>
  <div class="activity">Activity Feed</div>
  <div class="tasks">Task List</div>
  <footer class="dash-footer">Footer</footer>
</div>
css
.dashboard {
  display: grid;
  grid-template-columns: 250px repeat(3, 1fr);
  grid-template-rows: auto 200px 300px 250px auto;
  min-height: 100vh;
  gap: 15px;
  padding: 15px;
  background-color: #f5f5f5;
  grid-template-areas:
    "header     header      header      header"
    "sidebar    stats       stats       stats"
    "sidebar    chart-main  chart-main  chart-sub"
    "sidebar    activity    tasks       tasks"
    "footer     footer      footer      footer";
}

.dash-header {
  grid-area: header;
  background-color: #2196f3;
  color: white;
  padding: 20px;
  border-radius: 8px;
  font-size: 24px;
  font-weight: bold;
}

.dash-sidebar {
  grid-area: sidebar;
  background-color: #263238;
  color: white;
  padding: 20px;
  border-radius: 8px;
}

.stats {
  grid-area: stats;
  background-color: white;
  padding: 20px;
  border-radius: 8px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.chart-main {
  grid-area: chart-main;
  background-color: white;
  padding: 20px;
  border-radius: 8px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.chart-sub {
  grid-area: chart-sub;
  background-color: white;
  padding: 20px;
  border-radius: 8px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.activity {
  grid-area: activity;
  background-color: white;
  padding: 20px;
  border-radius: 8px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.tasks {
  grid-area: tasks;
  background-color: white;
  padding: 20px;
  border-radius: 8px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.dash-footer {
  grid-area: footer;
  background-color: #263238;
  color: white;
  padding: 15px;
  border-radius: 8px;
  text-align: center;
}

Application Layout โ€‹

Template areas are perfect for defining the overall structure of applications:

css
.app-layout {
  display: grid;
  grid-template-columns: 60px 200px 1fr 300px;
  grid-template-rows: 60px 1fr 40px;
  height: 100vh;
  grid-template-areas:
    "icon-bar app-header app-header app-header"
    "icon-bar sidebar     main       panel"
    "icon-bar status-bar  status-bar status-bar";
}

.icon-bar {
  grid-area: icon-bar;
  background-color: #37474f;
}

.app-header {
  grid-area: app-header;
  background-color: #fff;
  border-bottom: 1px solid #ddd;
}

.sidebar {
  grid-area: sidebar;
  background-color: #f5f5f5;
  border-right: 1px solid #ddd;
}

.main {
  grid-area: main;
  background-color: #fff;
  overflow-y: auto;
}

.panel {
  grid-area: panel;
  background-color: #fafafa;
  border-left: 1px solid #ddd;
}

.status-bar {
  grid-area: status-bar;
  background-color: #2196f3;
  color: white;
}

Responsive Template Areas โ€‹

The true power of template areas comes from working with media queries to implement responsive layouts. You can redefine grid-template-areas for different screen sizes, achieving completely different layouts.

Mobile-First Blog Layout โ€‹

css
/* Mobile: Single column layout */
.blog-layout {
  display: grid;
  grid-template-columns: 1fr;
  grid-template-rows: auto;
  gap: 15px;
  padding: 15px;
  grid-template-areas:
    "header"
    "nav"
    "post"
    "widgets"
    "sidebar"
    "footer";
}

/* Tablet: Two column layout */
@media (min-width: 768px) {
  .blog-layout {
    grid-template-columns: 2fr 1fr;
    grid-template-areas:
      "header  header"
      "nav     nav"
      "post    widgets"
      "post    sidebar"
      "footer  footer";
  }
}

/* Desktop: Three column layout */
@media (min-width: 1024px) {
  .blog-layout {
    grid-template-columns: 200px 1fr 300px;
    grid-template-areas:
      "header  header  header"
      "nav     nav     nav"
      "sidebar post    widgets"
      "footer  footer  footer";
  }
}

See how by redefining grid-template-areas, we achieve completely different layouts on different screens:

Mobile (less than 768px):

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ Header  โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Nav     โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Post    โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Widgets โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Sidebar โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Footer  โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Tablet (768px - 1023px):

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ Header โ”‚ Header โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Nav    โ”‚ Nav    โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Post   โ”‚Widgets โ”‚
โ”‚        โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚        โ”‚Sidebar โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Footer โ”‚ Footer โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Desktop (1024px+):

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ Header โ”‚ Header โ”‚ Header โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Nav    โ”‚ Nav    โ”‚ Nav    โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚Sidebar โ”‚ Post   โ”‚Widgets โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Footer โ”‚ Footer โ”‚ Footer โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Progressive Dashboard Enhancement โ€‹

css
/* Mobile: Vertical stacking */
.dashboard {
  display: grid;
  grid-template-columns: 1fr;
  gap: 10px;
  padding: 10px;
  grid-template-areas:
    "header"
    "stats"
    "chart-main"
    "chart-sub"
    "activity"
    "tasks";
}

/* Hide sidebar and footer on mobile */
.dash-sidebar,
.dash-footer {
  display: none;
}

/* Tablet: Two columns + sidebar */
@media (min-width: 768px) {
  .dashboard {
    grid-template-columns: 200px 1fr;
    grid-template-areas:
      "header     header"
      "sidebar    stats"
      "sidebar    chart-main"
      "sidebar    chart-sub"
      "sidebar    activity"
      "sidebar    tasks";
  }

  .dash-sidebar {
    display: block;
    grid-area: sidebar;
  }
}

/* Desktop: Full layout */
@media (min-width: 1200px) {
  .dashboard {
    grid-template-columns: 250px repeat(3, 1fr);
    grid-template-rows: auto 200px 300px 250px auto;
    grid-template-areas:
      "header     header      header      header"
      "sidebar    stats       stats       stats"
      "sidebar    chart-main  chart-main  chart-sub"
      "sidebar    activity    tasks       tasks"
      "footer     footer      footer      footer";
  }

  .dash-footer {
    display: block;
    grid-area: footer;
  }
}

Template Areas vs. Line-Based Positioning โ€‹

Let's compare these two methods to help you choose the most appropriate one.

Line-Based Positioning โ€‹

css
.grid {
  display: grid;
  grid-template-columns: 200px 1fr 300px;
  grid-template-rows: auto 1fr auto;
}

.header {
  grid-column: 1 / 4;
  grid-row: 1;
}

.sidebar {
  grid-column: 1;
  grid-row: 2;
}

.main {
  grid-column: 2;
  grid-row: 2;
}

.aside {
  grid-column: 3;
  grid-row: 2;
}

.footer {
  grid-column: 1 / 4;
  grid-row: 3;
}

Pros:

  • More flexible, allows precise control
  • Can create non-rectangular arrangements
  • Suitable for dynamic content and complex calculations

Cons:

  • Code is less intuitive
  • Requires remembering grid structure during maintenance
  • Hard to see the overall layout at a glance

Template Areas โ€‹

css
.grid {
  display: grid;
  grid-template-columns: 200px 1fr 300px;
  grid-template-rows: auto 1fr auto;
  grid-template-areas:
    "header header header"
    "sidebar main  aside"
    "footer footer footer";
}

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

Pros:

  • Code reads like a layout diagram
  • Easy to maintain, see structure at a glance
  • Simple responsive adjustments
  • Semantic, self-explanatory

Cons:

  • Can only create rectangular areas
  • Not suitable for scenarios requiring precise numerical control
  • Areas must be contiguous (cannot skip cells)

When to Use Which Method? โ€‹

Use Template Areas:

  • Overall page layout
  • Clear area divisions
  • Need responsive adjustments
  • Team collaboration projects (code is more readable)

Use Line-Based Positioning:

  • Need non-rectangular arrangements
  • Dynamic content (variable quantities)
  • Need precise numerical control
  • Complex overlapping layouts

Combination Usage:

css
/* Use template areas for main structure */
.page {
  display: grid;
  grid-template-columns: 200px 1fr;
  grid-template-rows: auto 1fr auto;
  grid-template-areas:
    "header  header"
    "sidebar main"
    "footer  footer";
}

/* Use line-based positioning inside main content area */
.main {
  grid-area: main;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 20px;
}

Common Issues and Solutions โ€‹

Issue 1: Spelling Errors in Area Names โ€‹

css
.grid {
  grid-template-areas:
    "header header"
    "main   aside";
}

.content {
  grid-area: mian; /* Spelling error! Should be main */
}

Solution: Use editor auto-completion or define constants:

css
/* You can list all area names in comments */
.grid {
  /* Areas: header, main, aside, footer */
  grid-template-areas:
    "header header"
    "main   aside";
}

Issue 2: Forgetting to Define All Cells โ€‹

css
/* โŒ Error: Inconsistent cell count per row */
.grid {
  grid-template-areas:
    "header header header"
    "main   aside"; /* Only 2 cells, should have 3! */
}

Solution: Ensure each row has the same number of cells, use . for empty cells:

css
/* โœ… Correct */
.grid {
  grid-template-areas:
    "header header header"
    "main   aside  ."; /* Third cell left empty */
}

Issue 3: Selector Duplication in Responsive Layouts โ€‹

css
/* โŒ Redundant */
.header {
  grid-area: header;
}

@media (min-width: 768px) {
  .header {
    grid-area: header;
  } /* Duplicate definition */
}

Solution: grid-area only needs to be defined once; in media queries, only change grid-template-areas:

css
/* โœ… Concise */
.header {
  grid-area: header;
} /* Define only once */

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

@media (min-width: 768px) {
  .grid {
    grid-template-areas: "header header" "sidebar main";
    /* Only change template, don't redefine grid-area */
  }
}

Summary โ€‹

Grid Template Areas is a powerful and intuitive way to create layouts, making your code as clear as a visual layout diagram.

Core Concepts Review:

  • grid-template-areas: Define named area layouts on the container
  • grid-area: Specify which area an item belongs to on the item
  • Use periods (.) to represent empty cells
  • Areas must form rectangles

Key Advantages:

  1. Intuitive and readable: Code reads like a visual layout diagram
  2. Easy to maintain: See the overall structure at a glance
  3. Semantic: Use meaningful names instead of numbers
  4. Responsive-friendly: Easily redefine layouts for different screens

Best Practices:

  • Use descriptive area names
  • Maintain grid-template-areas alignment for readability
  • Work with semantic HTML tags
  • Redefine templates for different screen sizes
  • Combine with line-based positioning when precise control is needed

Use Cases:

  • Overall page layout
  • Designs with clear area divisions
  • Layouts that need responsive adjustments
  • Team collaboration projects

Mastering Grid Template Areas allows you to create complex layouts in the most intuitive way. In the next section, we'll learn how to create fully responsive Grid layouts that render perfectly on any device.