Grid Tutorial - The Holy Grail (of) Layout
Tags: css, cssgrid, layout
Published: 2019-10-28 09:47:53

*Originally published in Web Designer Mag: March 2017*

Code: http://codepen.io/collection/DEgogB/

---

The idea here is to build the holy grail layout in Grid, but obviously it needs to be responsive. In case you don't know the holy grail layout is a header, a left sidebar, content area, right sidebar and then a footer. The code to accomplish this complex layout is pretty short and really easy to follow and understand, the syntax and new properties in Grid are not only simple but somehow elegant.

Just as a bonus, we've also got that much asked for feature of the footer being at the bottom of the viewport when the content isn't long enough to fill it. With a little help from the `minmax()` function.

As this demo is built using Grid you may need to turn on the appropriate browser flag until Grid is fully supported.

## Step One - The HTML
As always, you can't style elements that don't exist. So we have a containing `div` with the class of `grid` and inside that the five elements we need to create our holy grail layout, `<header>`,`<article>`,`<aside>`x2 and `<footer>`. Then added the class of `grid-item` to each of the elements and added a class to the sidebars to differentiate them in the CSS. Drop in the header from the last tutorial if you like too, Grid and Flexbox get along just fine.
(http://codepen.io/matchboxhero/pen/pRLwJY)

## Step Two - Named Areas
Jumping into the CSS we're going to start naming our elements to create a grid template. Mobile first, we will create our grid template. It's worth noting that you can have the `grid-template-areas` property span multiple lines in your CSS to represent the rows, allowing you to literally (ASCII style) describe the layout of your grid.

```
.grid {
	display: grid;
	grid-template-areas:
		"header"
		"article"
		"left-sidebar"
		"right-sidebar"
		"footer"
	;
	grid-template-columns: 1fr;
}
```

As you can see we have literally described in our template the layout we want the grid to use. We have also defined how many columns we want we setting it to `1fr` we're saying, there is one column and it should span the whole available width. 
(http://codepen.io/matchboxhero/pen/ggeRPv)

## Step Three - Responsive
The next step is to start adding media queries to redefine the grid template at a certain breakpoint. Since we want the layout to now have two columns in the middle we need to define these. At this breakpoint we want the header to span the entire first row and the footer the last;

```
@media (min-width: 540px) {
  .grid {
		grid-template-areas: 
			"header header"
			"left-sidebar article"
			"right-sidebar right-sidebar"
			"footer footer"
		;
		grid-template-columns: 1fr 2fr;
  }
}
```

By repeating the name of the area Grid knows the element should span two columns, you can also do the same thing with rows. The left sidebar and article are being split into thirds, one third being applied to the sidebar and two thirds the article.
(http://codepen.io/matchboxhero/pen/VPXWmW)

## Step Four - Wow, really?
Now we repeat the previous step but change some of the values, so at a larger breakpoint the article and sidebars will all be on the same row.

```
@media (min-width: 1200px) {
  .grid {
		grid-template-areas: 
			"header header header"
			"left-sidebar article right-sidebar"
			"footer footer footer"
		;
		grid-template-columns: 1fr 3fr 1fr;
  }
}
```

The `grid-template-areas` property can override the order of the DOM allowing for any layout you can dream up and the ability to change and reorder it, every 50px if you want to. Please don't, but you could.
(http://codepen.io/matchboxhero/pen/KaoqGK)

## Step Five - Bonus round
That's it, the holy grail layout built in Grid with 2 simple media-queries. Just as a bonus lets make the footer sick to the bottom of the page when there is not enough content to fill the viewport. We accomplish this by first applying a minimum height to the grid of the viewport height, that works but the header and footer are stretched vertically to fill the leftover space. We can use the minmax() function to stop the header and footer from expanding by defining the grids rows.

```
.grid {
	min-height: 100vh;
	height: 100vh; /* required by chrome */

	grid-template-rows: 
		minmax(min-content, max-content) 
		auto 
		minmax(min-content, max-content)
	;

}
```

Using the `min-content` and `max-content` keyword values inside the minmax() function we've told the header and footer not to grow into the available space, allowing the middle row to use all of the extra space.
(http://codepen.io/matchboxhero/pen/JELoxx)

## ALL CODE
```
header {
  grid-area: header;
}

.left {
  grid-area: left-sidebar;
}

.right {
  grid-area: right-sidebar;
}

article {
  grid-area: article;
}

footer {
  grid-area: footer;
}

.grid {
	display: grid;
	min-height: 100vh;
	height: 100vh;
	grid-template-areas:
		"header"
		"article"
		"left-sidebar"
		"right-sidebar"
		"footer"
	;
	grid-template-columns: 1fr;
}

@media (min-width: 540px) {
  .grid {
		grid-template-areas: 
			"header header"
			"left-sidebar article"
			"right-sidebar right-sidebar"
			"footer footer"
		;
		grid-template-columns: 1fr 2fr;
  }
}

@media (min-width: 1200px) {
  .grid {
		grid-template-areas: 
			"header header header"
			"left-sidebar article right-sidebar"
			"footer footer footer"
		;
		grid-template-columns: 1fr 3fr 1fr;
  }
}

.grid-item {
  padding: 24px;
}
```