How to create the Holy Grail Layout with CSS Grid

By Hunter Becton on October 6, 2022

Scalable and easily adaptable to different devices, CSS Grid helps us create layouts that are easier to build and maintain. What makes CSS Grid so incredible is its ability to automatically resized columns accordingly to the device's width. But how could we use CSS Grid to create a Holy Grail Layout? Let's find out!

Watch the lesson

What is the Holy Grail Layout?

The Holy Grail Layout refers to a layout that features a header, footer, left sidebar, right sidebar, and main content. In the early 2000s, it wasn't easy to achieve this layout using existing web technologies, hence the name. Today, you can build this layout quickly with CSS Grid or Flexbox.

Write the HTML

The HTML for the Holy Grail Layout is simple. All you need to do is create the main container and include the five sections using semantic HTML elements. Those semantic elements include the header, nav, main, aside, and footer HTML elements.

Below is what your HTML should look like:

<div class="container">
  <header></header>
  <nav></nav>
  <main></main>
  <aside></aside>
  <footer></footer>
</div>

Create the CSS Grid

With the HTML complete, it's now time to move to style the Holy Grail Layout with CSS. 

First, we need to let CSS know we're using grid by setting display to grid

Next, we need to create the columns for our grid using the grid-template-columns property. As the property name suggests, this will define the three columns in our grid, which are 16rem1fr, and 16rem

By setting our columns to these values, the left and right columns will have a fixed width, and the middle column will adjust to fill the remaining space. In our video, Create Responsive Layouts with This One CSS Grid Feature, you can learn more about fractional units.

With the columns defined, it's time to define the three rows. To do this, we'll use the grid-template-rows property. The values we'll set here are auto1fr, and auto. The first and last rows are set to auto and adjust their height to fill the content inside. The middle row behaves similarly to the middle column and will take up the remaining space.

Your CSS should look like the following so far in the tutorial:

.container {
  display: grid;
  grid-template-columns: 16rem 1fr 16rem;
  grid-template-rows: auto 1fr auto;
}

Build the layout with grid-template-areas

Now that our grid is defined, it's time to start placing our elements on the grid! To do this, we'll use one of my favorite CSS Grid properties, grid-template-areas.

Before we place the items using grid-template-areas, we first must give each element a name that we'll use to refer to the specific element. The CSS property we'll use to do this is grid-area. You can name these elements anything you want, but I'd suggest keeping them relevant and easy to remember.

Here's the CSS I have for naming the specific elements with grid-area:

header {
  grid-area: header;
  padding: 2rem;
  background-color: #1e293b;
}

nav {
  grid-area: nav;
  padding: 2rem;
  background-color: #334155;
}

main {
  grid-area: content;
  padding: 2rem;
  background-color: #475569;
}

aside {
  grid-area: sidebar;
  padding: 2rem;
  background-color: #64748b;
}

footer {
  grid-area: footer;
  padding: 2rem;
  background-color: #94a3b8;
}

Now that the elements are defined, we can finally refer to them using grid-template-areas. The syntax for this property is a bit unique, but don't worry because it's simple to understand!

As you recall, we created a grid with three columns and three rows. Here's a visual example representation of that grid:

X X X

X X X

X X X

We need to replace the Xs with the element's name we create using grid-area. That would look something like the following:

header header header

nav content sidebar

footer footer footer

Now, wrap each row in quotations, and you'll have the proper syntax for the grid-template-areas:

.container {
  display: grid;
  grid-template-columns: 16rem 1fr 16rem;
  grid-template-rows: auto 1fr auto;
  grid-template-areas:
    "header header header"
    "nav content sidebar"
    "footer footer footer";
}

Make the layout responsive

Now that our elements are on the grid, we must ensure everything looks great across all devices. To achieve this responsiveness, we'll be using CSS media queries. The first media query is for a max-width of 1024px.

In this media query, we'll first adjust the overall grid by setting grid-template-columns to 1fr. This change will change the grid from three columns to one that will fill the page's entire width.

Next, we will adjust the rows by changing the grid-template-rows property to autominmax(5rem, auto)1frminmax(5rem, auto), and auto. We've already discussed most of the values above, but there is a new value that uses the minmax CSS function. This function allows us to set a minimum and maximum height at once for our nav and sidebar. 

Now that our grid is adjusted, we can go ahead and define the grid-template-areas:

@media (max-width: 64rem) {
  .container {
    grid-template-columns: 1fr;
    grid-template-rows: auto minmax(5rem, auto) 1fr minmax(5rem, auto) auto;
    grid-template-areas:
      "header"
      "nav"
      "content"
      "sidebar"
      "footer";
  }
}

Conclusion

All in all, CSS Grid is just one more tool at our disposal. It certainly isn't perfect, but it's working its way there, and there are strategies to make the most of what it offers. 

Hopefully, this article will provide a starting point from which you can build your layouts with CSS Grid. At the very least, it should give you an idea of how CSS Grid might fit into your workflow in the future.