Why does a grid-area name absent in grid-template-areas create additional tracks?

There are four parts to this answer. The first three help explain the fourth, which covers the reason for the extra column. If you’re only interested in the answer, skip to the end.

Contents:

  1. More than meets the eye: There’s also an extra row!
  2. The grid-area property.
  3. The grid-template-areas property.
  4. The placement of unreferenced grid areas.

1. More than meets the eye: There’s also an extra row!

You’ve only partially defined the problem. Yes, there’s an extra column. But there’s also an extra row.

Because you haven’t defined a height on the grid container, the height defaults to auto – the height of the content (more details). So any rows with no content simply collapse and are invisible.

This issue doesn’t exist with width because, in this case, you’re using a block-level container (created by display: grid), which is designed to consume the full width of its parent, by default (more details).

So that’s why you’re not seeing the extra row. If you give the container some height, the row will appear.

body {
  display: grid;
  grid-template-areas:
    "header"
    "footer";
  height: 150px; /* new */ 
}

enter image description here

body {
  display: grid;
  grid-template-areas:
    "header"
    "footer";
  height: 150px; /* new */
}

header {
  grid-area: header;
  background: aqua;
}

main {
  grid-area: main;
  background: darkorange;
}

footer {
  grid-area: footer;
  background: lightgreen;
}
<header>Header</header>
<main>Main</main>
<footer>Footer</footer>

Note: If you had used display: inline-grid, both the extra row and the extra column would have been invisible.

body {
  display: inline-grid;
  grid-template-areas:
    "header"
    "footer";
}

enter image description here

body {
  display: inline-grid; /* adjustment */
  grid-template-areas:
    "header"
    "footer";
}

header {
  grid-area: header;
  background: aqua;
}

main {
  grid-area: main;
  background: darkorange;
}

footer {
  grid-area: footer;
  background: lightgreen;
}
<header>Header</header>
<main>Main</main>
<footer>Footer</footer>

2. The grid-area property.

Giving a name to the grid-area property creates a named line for each side of the area.

For example, grid-area: header resolves, in order, like this:

  • grid-row-start: header
  • grid-column-start: header
  • grid-row-end: header
  • grid-column-end: header

Like margin, border and padding, the grid-area property is a shorthand property. Unlike those properties, grid-area has a counterclockwise resolution order (in LTR languages), as illustrated above.

Because named grid areas occupy space, they need rows and columns in which to exist. Hence, named grid areas always impact the layout, even when they’re not referenced in grid-template-areas.

So all that is necessary to “fix” your layout is to remove grid-area: main.

main {
  /* grid-area: main; */
  background: darkorange;
}

enter image description here

body {
  display: grid;
  grid-template-areas:
    "header"
    "footer";
}

header {
  grid-area: header;
  background: aqua;
}

main {
  /* grid-area: main; */
  background: darkorange;
}

footer {
  grid-area: footer;
  background: lightgreen;
}
<header>Header</header>
<main>Main</main>
<footer>Footer</footer>

3. The grid-template-areas property.

Rows and columns (a/k/a tracks) that are created using grid-template-rows, grid-template-columns or grid-template-areas belong to the explicit grid. Any tracks not defined by those properties belong to the implicit grid (source).

For every string listed in grid-template-areas, a new row is created.

For every name or sequence of dots (...) in the string, a new column is created (but this doesn’t apply in this case because each string has only one name).

Your code creates an explicit grid with two rows and one column:

body {
  display: grid;
  grid-template-areas: 
    "header"
    "footer";
}

enter image description here

As you can see in the image, header and footer have their own rows and exist in column one, exactly as defined in grid-template-areas.

The additional two rows and two columns are part of the implicit grid.

We can verify this by sizing them.

grid-template-columns works only on explicit columns.

grid-auto-columns works mostly on implicit columns (see note below).

body {
  display: grid;
  grid-template-areas: "header" "footer";
  grid-template-columns: 1fr;
  grid-auto-columns: 100px;
  grid-template-rows: 100px 100px;
  grid-auto-rows: 25px;
}

enter image description here

body {
  display: grid;
  grid-template-areas:
      "header"
      "footer";
  grid-template-columns: 1fr;
  grid-auto-columns: 100px;
  grid-template-rows: 100px 100px;
  grid-auto-rows: 25px;
}

header {
  grid-area: header;
  background: aqua;
}

main {
  grid-area: main;
  background: darkorange;
}

footer {
  grid-area: footer;
  background: lightgreen;
}
<header>Header</header>
<main>Main</main>
<footer>Footer</footer>

Note: If grid items are placed using grid-template-areas (creating explicit tracks), but they are not sized using grid-template-columns / grid-template-rows, then grid-auto-columns / grid-auto-rows apply to them. (second paragraph)

body {
  display: grid;
  grid-template-areas:
      "header"
      "footer";
  grid-auto-columns: 100px;
  grid-auto-rows: 25px;
}

enter image description here

body {
  display: grid;
  grid-template-areas:
      "header"
      "footer";
  grid-auto-columns: 100px;
  grid-auto-rows: 25px;
}

header {
  grid-area: header;
  background: aqua;
}

main {
  grid-area: main;
  background: darkorange;
}

footer {
  grid-area: footer;
  background: lightgreen;
}
<header>Header</header>
<main>Main</main>
<footer>Footer</footer>

4. The placement of unreferenced grid areas.

Note: To be perfectly honest, I’m about 75% sure this section is completely correct. The spec language was not 100% clear to me. I welcome feedback, corrections, and more accurate answers.

In your code you have a third grid area which is not referenced in grid-template-areas.

body {
  display: grid;
  grid-template-areas: 
    "header"
    "footer";
}

main {
  grid-area: main;
  background: darkorange;
}

Where does grid-area: main go?

As we’ve already seen, it gets sent into the implicit grid, two columns and two rows in.

enter image description here

The grid area is handled by the grid auto-placement algorithm, which appears to say this:

  1. Because grid-area: main isn’t explicitly defined (see section 3 above), it belongs in the implicit grid.

  2. Because grid column line 2 and grid row line 3 (the boundaries of the explicit grid) are named grid lines, new lines must be created in the implicit grid to accommodate the four named lines of grid-area: main. This can only happen with an empty row and empty column in between, separating the explicit grid from the auto-placed implicit grid area.

Leave a Comment