HTML Formatterhtmlformatteronline.com

Holy grail layout

Header, footer, two sidebars and a main column — in nine lines of grid.

layoutgridholy grailsidebarpage
<div class="page">
  <header>Header</header>
  <nav>Navigation</nav>
  <main>
    <h1>Main content</h1>
    <p>This column takes whatever space the two sidebars leave. Resize the preview to see the
    sidebars move above and below it.</p>
  </main>
  <aside>Aside</aside>
  <footer>Footer</footer>
</div>

How it works

This layout was hard enough in the float era that it got a nickname. With grid template areas it is one property, and you can read the page shape directly out of the CSS.

The areas diagram is the layout. The three quoted rows in grid-template-areas are a picture of the page. Changing the arrangement means editing that diagram, not recalculating widths and margins.

1fr in the middle column means main takes whatever the two fixed sidebars leave. No calc(100% - 400px), and it stays correct if you change a sidebar width.

1fr on the middle row plus min-height: 100vh pushes the footer to the bottom of the viewport on a short page, and lets it sit below the content on a long one. This is the sticky-footer problem, solved for free as a side effect.

Main comes second in the mobile order, not third. The source order is header, nav, main, aside, footer — which is the right reading order for assistive technology. On mobile the areas diagram promotes main above nav so the content appears first visually. Grid lets the two orders differ, which is exactly the case this feature exists for.

Accessibility notes

Every region is a real landmark element — header, nav, main, aside, footer — rather than five divs with classes. Screen reader users navigate by landmark, and this gives them the whole page structure for free.

Only one <main> per page. If you have two <nav> elements, give each an aria-label so they can be told apart.

Because grid can reorder visually without changing the DOM, check that your tab order still makes sense after a reorder. Here it does: main is after nav in the source, so keyboard users reach navigation first, which is the conventional order.

Making it yours

Sidebar widths are the two fixed values in grid-template-columns. Use minmax(160px, 220px) instead of a fixed pixel value if you want them to flex a little before the layout breaks to one column.

For a left sidebar only, delete aside from the markup and use two columns. The areas diagram is the only place you need to change.

Take care with 100vh on mobile browsers: the value includes the area behind the address bar, so a full-height layout can be slightly taller than the visible screen. 100dvh fixes it where supported, and degrades to the same behaviour where it is not.

Related templates

Check your version

Once you have edited this, the HTML validator will catch any tag you left unclosed, and the formatter will tidy the indentation. Both run in your browser.