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:
- More than meets the eye: There’s also an extra row!
- The
grid-area
property. - The
grid-template-areas
property. - 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 */
}
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";
}
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;
}
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";
}
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;
}
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;
}
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.
The grid area is handled by the grid auto-placement algorithm, which appears to say this:
-
Because
grid-area: main
isn’t explicitly defined (see section 3 above), it belongs in the implicit grid. -
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.