The Holy Grail Layout with CSS Grid

Avatar of Chris Coyier
Chris Coyier on

A reader wrote in asking specifically how to build this layout in CSS Flexbox:

My answer: That’s not really a layout for CSS Flexbox. You could pull it off if you had to, but you’d need some kind of conceit, like grouping the nav and article together in a parent element (if not more grouping). CSS Grid was born to describe this kind of layout and it will be far easier to work with, not to mention that the browser support for both is largely the same these days.

What do you mean by “Holy Grail”?

See, kids, layout on the web used to be so janky that the incredible simple diagram above was relatively difficult to pull off, particularly if you needed the “columns” there to match heights. I know, ridiculous, but that was the deal. We used super weird hacks to get it done (like huge negative margins paired with positive padding), which evolved over time to cleaner tricks (like background images that mimicked columns). Techniques that did manage to pull it off referred to it as the holy grail. (Just for extra clarity, usually, holy grail meant a three-column layout with content in the middle, but the main point was equal height columns).

CSS is much more robust now, so we can use it without resorting to hacks to do reasonable things, like accomplish this basic layout.

Here it is in CSS Grid

This grid is set up both with grid-template-columns and grid-template-rows. This way we can be really specific about where we want these major site sections to fall.

I slipped in some extra stuff

  • I had another question come my way the other day about doing 1px lines between grid areas. The trick there is as simple as the parent having a background color and using gap: 1px;, so I’ve done that in the demo above.
  • It’s likely that small screens move down to a single-column layout. I’ve done that at a media query above. Sometimes I use display: block; on the parent, turning off the grid, but here I’ve left grid on and reset the columns and rows. This way, we still get the gap, and we can shuffle things around if needed.
  • Another recent question I was asked about is the subtle “body border” effect you can see in the demo above. I did it about as simple as possible, with a smidge of padding between the body and the grid wrapper. I originally did it between the body and the HTML element, but for full-page grids, I think it’s smarter to use a wrapper div than use the body for the grid. That way, third-party things that inject stuff into the body won’t cause layout weirdness.