CSS Tutorial – The Holy Grail Layout with CSS Grid


Rengga Dev – 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

<div class="page-wrap">
  <header class="page-header">
    Header
  </header>
  <nav class="page-nav">
    Nav
  </nav>
  <main class="page-main">
    <article>
      <details>
        <summary>Article</summary>
        <p>Lorem ipsum dolor, sit amet consectetur adipisicing elit. Dignissimos laborum cumque incidunt, enim ipsa dicta? Porro illo doloribus, consectetur eum exercitationem sit ipsam, est nesciunt maxime, eius animi dolor? Harum.</p>
        <p>Commodi culpa deserunt dolor sed, ipsam tempore ullam architecto fuga voluptas, quis veniam. Vitae veniam, odit adipisci, quas similique debitis excepturi quisquam minima facere temporibus, porro optio perferendis iusto fuga.</p>
        <p>Illo numquam, sapiente neque repellendus facere amet doloribus asperiores quia eum? Sunt vero amet neque vel? Tempora, nulla voluptatum amet autem culpa magnam debitis! Dolores esse quam amet nobis ut.</p>
        <p>Sunt excepturi in nostrum, fugiat veritatis ab sit sequi nemo aperiam deserunt temporibus, dolorem ex adipisci autem. Quasi, iure fugiat! Nulla amet doloribus velit nam tempora, soluta consequatur doloremque omnis?</p>
        <p>Officia ea repellat ad, sapiente eligendi modi magni quos temporibus totam culpa corporis, dignissimos quibusdam mollitia dolore eaque suscipit soluta beatae ipsam! Aperiam doloremque vero soluta pariatur possimus. Cupiditate, fuga.</p>
        <p>Beatae deserunt veritatis magni quis quae enim ad est dignissimos iste, quidem, dolores temporibus asperiores natus inventore, nobis eius facere adipisci doloremque eligendi autem magnam excepturi? Inventore, iusto soluta. Maiores.</p>
        <p>Enim facilis aspernatur, maiores unde at inventore temporibus minima possimus eveniet? Cum alias, asperiores quibusdam doloribus, vel ullam qui in dicta recusandae eaque atque dolor perspiciatis tenetur, fugit vero reprehenderit.</p>
        <p>Reiciendis, deleniti eius nostrum fugit commodi quasi esse molestias non voluptates, corrupti excepturi voluptatibus, consequatur ipsa animi placeat quia corporis ut itaque quos pariatur inventore. Quasi incidunt sapiente quisquam soluta?</p>
        <p>Laboriosam eos atque possimus assumenda quia voluptatem saepe optio, eveniet laborum. Sit esse doloremque laboriosam? Ullam inventore ut facilis accusamus, ipsum, autem labore incidunt consequatur eos dolorem, sit aperiam odit.</p>
        <p>Consequuntur pariatur illum doloremque, necessitatibus praesentium quis cumque officiis non commodi reprehenderit quaerat velit saepe impedit vitae dolores, veritatis reiciendis ducimus nobis totam, itaque porro temporibus excepturi error iste! Sunt.</p>
        <p>Commodi culpa deserunt dolor sed, ipsam tempore ullam architecto fuga voluptas, quis veniam. Vitae veniam, odit adipisci, quas similique debitis excepturi quisquam minima facere temporibus, porro optio perferendis iusto fuga.</p>
        <p>Illo numquam, sapiente neque repellendus facere amet doloribus asperiores quia eum? Sunt vero amet neque vel? Tempora, nulla voluptatum amet autem culpa magnam debitis! Dolores esse quam amet nobis ut.</p>
        <p>Sunt excepturi in nostrum, fugiat veritatis ab sit sequi nemo aperiam deserunt temporibus, dolorem ex adipisci autem. Quasi, iure fugiat! Nulla amet doloribus velit nam tempora, soluta consequatur doloremque omnis?</p>
        <p>Officia ea repellat ad, sapiente eligendi modi magni quos temporibus totam culpa corporis, dignissimos quibusdam mollitia dolore eaque suscipit soluta beatae ipsam! Aperiam doloremque vero soluta pariatur possimus. Cupiditate, fuga.</p>
      </details>
    </article>
  </main>
  <aside class="page-sidebar">
    Aside
  </aside>
  <footer class="page-footer">
    Footer
  </footer>
</div>
* {
  box-sizing: border-box;
}
body {
  background: #e4e4e4;
  padding: 5px;
  height: 100vh;
  margin: 0;

  font: 500 100% system-ui, sans-serif;
  text-transform: uppercase;
}
.page-wrap {
  background: white;
  height: calc(100vh - 10px);
  box-shadow: 0 0 3px rgba(black, 0.33);

  display: grid;
  grid-template-columns: minmax(10px, 1fr) minmax(10px, 3fr);
  grid-template-rows: min-content min-content 1fr min-content;
  gap: 1px;

  > * {
    padding: 1rem;
    text-align: center;
  }

  @media (max-width: 600px) {
    grid-template-columns: 100%;
    grid-template-rows: auto;
    > * {
      grid-column: 1 / -1 !important;
      grid-row: auto !important;
    }
  }
}

.page-header {
  grid-column: 1 / -1;
  background: #ffcdd2;
}

.page-sidebar {
  grid-column: 1 / 2;
  grid-row: 2 / 4;
  background: #e1bee7;
}
.page-nav {
  grid-column: 2 / 3;
  background: #bbdefb;
}
.page-main {
  grid-column: 2 / 3;
  background: #dcedc8;
}
.page-footer {
  grid-column: 1 / -1;
  background: #ffecb3;
}

details p {
  text-transform: none;
  text-align: left;
}


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.
Nandemo Webtools

Leave a Reply