Skip to content
WebTricks

Holy grail layout (CSS Grid)

The classic header, sidebar, content, aside and footer layout in a few lines using grid-template-areas.

  • grid
  • layout
  • holy-grail
  • template-areas
  • page
Bar color#1f2330
Accent#7c5cff
Gap8px
HTML
<div class="layout"><header class="layout__h">Header</header><nav class="layout__nav">Nav</nav><main class="layout__main">Main content</main><aside class="layout__aside">Aside</aside><footer class="layout__f">Footer</footer></div>
CSS
:root {
    --bar: #1f2330;
    --accent: #7c5cff;
    --gap: 8px;
}

.layout {
    display: grid;
    gap: var(--gap);
    min-height: 260px;
    grid-template:
        "header header header" auto
        "nav    main   aside"  1fr
        "footer footer footer" auto
        / 100px 1fr 100px;
    color: #fff;
}

.layout__h    { grid-area: header; }
.layout__nav  { grid-area: nav; }
.layout__main { grid-area: main; }
.layout__aside{ grid-area: aside; }
.layout__f    { grid-area: footer; }

.layout > * {
    padding: 12px;
    border-radius: 8px;
    background: var(--bar);
}
.layout__h, .layout__f { border-block: 2px solid var(--accent); }

How it works

grid-template draws the whole page as a picture: each quoted row names the cells, and the sizes after the / set the column track widths.

  • The named areas (header, nav, main, aside, footer) are assigned to elements with grid-area, so the markup order doesn’t matter.
  • The middle row is 1fr — it grows to fill the height; the bars are auto.
  • Columns are 100px 1fr 100px: fixed sidebars hugging a flexible center.

To go single-column on mobile, just redefine the areas in a media query:

@media (max-width: 600px) {
  .layout {
    grid-template:
      "header" auto "nav" auto "main" 1fr
      "aside" auto "footer" auto / 1fr;
  }
}

For a card grid that reflows on its own, see the responsive grid with no media queries.