30 CSS Grid Layouts04 / 30

Pure CSSMIT licensed

Modern Holy Grail

The legendary header/nav/main/aside/footer layout — the one that needed floats, negative margins and prayer for fifteen years — rebuilt as eleven lines of grid-template-areas. Fluid center column via minmax(0,1fr), sidebars that never collapse below readable, and a single media query for mobile stacking.

Published

Live Demo
Try it

The code

<section class="cgl-04" aria-label="Modern holy grail layout demo">
  <div class="cgl-04__shell">
    <header class="cgl-04__header"><strong>header</strong><span>brand · search · account</span></header>
    <nav class="cgl-04__nav" aria-label="Primary"><strong>nav</strong><a href="#0">Dashboard</a><a href="#0">Projects</a><a href="#0">Reports</a><a href="#0">Settings</a></nav>
    <main class="cgl-04__main"><strong>main</strong><p>The fluid center: minmax(0, 1fr) absorbs all spare width and — crucially — is allowed to shrink below its content's natural size, so wide tables and code blocks scroll here instead of shoving the sidebars off-canvas.</p></main>
    <aside class="cgl-04__aside"><strong>aside</strong><p>Related links, ads, or a table of contents. Clamped between 140 and 200px.</p></aside>
    <footer class="cgl-04__footer"><strong>footer</strong><span>pinned by auto · 1fr · auto rows</span></footer>
  </div>
</section>
.cgl-04,
.cgl-04 *,
.cgl-04 *::before,
.cgl-04 *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.cgl-04 {
  width: 100%;
  min-height: 100vh;
  --bg: oklch(0.2 0.03 250);
  --line: oklch(0.75 0.12 210);
  --txt: oklch(0.93 0.01 220);
  --dim: oklch(0.7 0.03 230);
  font-family: ui-monospace,'Cascadia Code',Menlo,monospace;
  background: repeating-linear-gradient(0deg,transparent 0 23px,oklch(0.75 0.12 210/.06) 23px 24px),repeating-linear-gradient(90deg,transparent 0 23px,oklch(0.75 0.12 210/.06) 23px 24px),var(--bg);
  color: var(--txt);
  padding: 1.4rem;
}

.cgl-04 .cgl-04__shell {
  display: grid;
  grid-template-areas: "header header header" "nav main aside" "footer footer footer";
  grid-template-columns: minmax(140px,180px) minmax(0,1fr) minmax(140px,200px);
  grid-template-rows: auto 1fr auto;
  gap: 10px;
  min-block-size: 380px;
}

.cgl-04 .cgl-04__shell>* {
  border: 1px dashed color-mix(in oklab,var(--line) 55%,transparent);
  border-radius: 10px;
  padding: .9rem;
  background: oklch(0.24 0.03 250/.8);
}

.cgl-04 strong {
  display: block;
  font-size: .7rem;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--line);
  margin-block-end: .5rem;
}

.cgl-04 .cgl-04__header {
  grid-area: header;
  display: flex;
  align-items: baseline;
  gap: 1rem;
}

.cgl-04 .cgl-04__header strong {
  margin: 0;
}

.cgl-04 .cgl-04__header span,
.cgl-04 .cgl-04__footer span {
  font-size: .75rem;
  color: var(--dim);
}

.cgl-04 .cgl-04__nav {
  grid-area: nav;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.cgl-04 .cgl-04__nav a {
  font-size: .8rem;
  color: var(--dim);
  text-decoration: none;
  padding: .4rem .5rem;
  border-radius: 6px;
}

.cgl-04 .cgl-04__nav a:hover {
  color: var(--txt);
  background: oklch(0.3 0.04 250);
}

.cgl-04 .cgl-04__nav a:focus-visible {
  outline: 2px solid var(--line);
  outline-offset: 2px;
}

.cgl-04 .cgl-04__main {
  grid-area: main;
}

.cgl-04 .cgl-04__aside {
  grid-area: aside;
}

.cgl-04 .cgl-04__footer {
  grid-area: footer;
  display: flex;
  align-items: baseline;
  gap: 1rem;
}

.cgl-04 .cgl-04__footer strong {
  margin: 0;
}

.cgl-04 p {
  font-size: .8rem;
  line-height: 1.7;
  color: var(--dim);
}

@media (max-width: 640px) {
  .cgl-04 .cgl-04__shell {
    grid-template-areas: "header" "nav" "main" "aside" "footer";
    grid-template-columns: 1fr;
    grid-template-rows: auto;
  }
}
/* No JavaScript — grid-template-areas draws the page as ASCII art; one media query restacks it without touching the HTML. */
Paste this into ChatGPT, Claude, Cursor, or any coding assistant. The block below is pre-framed with everything the AI needs to integrate this demo into your project — markup, styles, scoping notes, and the source URL. Hit Copy and paste straight into your chat.
Here's a working CSS Grid Layout from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Modern Holy Grail
Source: https://codefronts.com/layouts/css-grid-layouts/modern-holy-grail/

The legendary header/nav/main/aside/footer layout — the one that needed floats, negative margins and prayer for fifteen years — rebuilt as eleven lines of grid-template-areas. Fluid center column via minmax(0,1fr), sidebars that never collapse below readable, and a single media query for mobile stacking.
## HTML
```html
<section class="cgl-04" aria-label="Modern holy grail layout demo">
  <div class="cgl-04__shell">
    <header class="cgl-04__header"><strong>header</strong><span>brand · search · account</span></header>
    <nav class="cgl-04__nav" aria-label="Primary"><strong>nav</strong><a href="#0">Dashboard</a><a href="#0">Projects</a><a href="#0">Reports</a><a href="#0">Settings</a></nav>
    <main class="cgl-04__main"><strong>main</strong><p>The fluid center: minmax(0, 1fr) absorbs all spare width and — crucially — is allowed to shrink below its content's natural size, so wide tables and code blocks scroll here instead of shoving the sidebars off-canvas.</p></main>
    <aside class="cgl-04__aside"><strong>aside</strong><p>Related links, ads, or a table of contents. Clamped between 140 and 200px.</p></aside>
    <footer class="cgl-04__footer"><strong>footer</strong><span>pinned by auto · 1fr · auto rows</span></footer>
  </div>
</section>
```
## CSS
```css
.cgl-04,
.cgl-04 *,
.cgl-04 *::before,
.cgl-04 *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.cgl-04 {
  width: 100%;
  min-height: 100vh;
  --bg: oklch(0.2 0.03 250);
  --line: oklch(0.75 0.12 210);
  --txt: oklch(0.93 0.01 220);
  --dim: oklch(0.7 0.03 230);
  font-family: ui-monospace,'Cascadia Code',Menlo,monospace;
  background: repeating-linear-gradient(0deg,transparent 0 23px,oklch(0.75 0.12 210/.06) 23px 24px),repeating-linear-gradient(90deg,transparent 0 23px,oklch(0.75 0.12 210/.06) 23px 24px),var(--bg);
  color: var(--txt);
  padding: 1.4rem;
}

.cgl-04 .cgl-04__shell {
  display: grid;
  grid-template-areas: "header header header" "nav main aside" "footer footer footer";
  grid-template-columns: minmax(140px,180px) minmax(0,1fr) minmax(140px,200px);
  grid-template-rows: auto 1fr auto;
  gap: 10px;
  min-block-size: 380px;
}

.cgl-04 .cgl-04__shell>* {
  border: 1px dashed color-mix(in oklab,var(--line) 55%,transparent);
  border-radius: 10px;
  padding: .9rem;
  background: oklch(0.24 0.03 250/.8);
}

.cgl-04 strong {
  display: block;
  font-size: .7rem;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--line);
  margin-block-end: .5rem;
}

.cgl-04 .cgl-04__header {
  grid-area: header;
  display: flex;
  align-items: baseline;
  gap: 1rem;
}

.cgl-04 .cgl-04__header strong {
  margin: 0;
}

.cgl-04 .cgl-04__header span,
.cgl-04 .cgl-04__footer span {
  font-size: .75rem;
  color: var(--dim);
}

.cgl-04 .cgl-04__nav {
  grid-area: nav;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.cgl-04 .cgl-04__nav a {
  font-size: .8rem;
  color: var(--dim);
  text-decoration: none;
  padding: .4rem .5rem;
  border-radius: 6px;
}

.cgl-04 .cgl-04__nav a:hover {
  color: var(--txt);
  background: oklch(0.3 0.04 250);
}

.cgl-04 .cgl-04__nav a:focus-visible {
  outline: 2px solid var(--line);
  outline-offset: 2px;
}

.cgl-04 .cgl-04__main {
  grid-area: main;
}

.cgl-04 .cgl-04__aside {
  grid-area: aside;
}

.cgl-04 .cgl-04__footer {
  grid-area: footer;
  display: flex;
  align-items: baseline;
  gap: 1rem;
}

.cgl-04 .cgl-04__footer strong {
  margin: 0;
}

.cgl-04 p {
  font-size: .8rem;
  line-height: 1.7;
  color: var(--dim);
}

@media (max-width: 640px) {
  .cgl-04 .cgl-04__shell {
    grid-template-areas: "header" "nav" "main" "aside" "footer";
    grid-template-columns: 1fr;
    grid-template-rows: auto;
  }
}
```

## JavaScript
```js
/* No JavaScript — grid-template-areas draws the page as ASCII art; one media query restacks it without touching the HTML. */
```

How this works

Five landmark elements map to five named areas: grid-template-areas: "header header header" "nav main aside" "footer footer footer" with grid-template-columns: minmax(140px, 180px) minmax(0, 1fr) minmax(140px, 200px). The ASCII-art syntax IS the documentation — you can read the page structure in the stylesheet.

grid-template-rows: auto 1fr auto plus min-block-size on the shell pins the footer to the bottom even when content is short — the classic sticky-footer problem solved as a by-product. The mobile query rewrites only the grid-template-areas string to a vertical stack; the HTML source order never changes, which keeps tab order and screen-reader order correct.

Make it yours

  • Drop the aside on content pages by removing one word from each areas string — no HTML change.
  • Swap nav and aside sides by editing the middle areas row.
  • Give the shell min-block-size: 100dvh in production for a true full-viewport app frame.
  • Tune sidebar clamps (140–200px) to your nav label lengths.

Gotchas — read before shipping

  • Every area name must form a rectangle — an L-shaped region silently invalidates the whole template.
  • Use minmax(0,1fr) for main; plain 1fr lets a wide code block push both sidebars off-screen.
  • Keep source order semantic (header→nav→main→aside→footer) and let areas do the visual placement — never reorder HTML for looks.

Browser support

ChromeSafariFirefoxEdge
111+16.2+113+111+

Floor set by oklch(), color-mix() as this demo is written. The core technique itself goes back further — Chrome 57+.

grid-template-areas is original-grid vintage — this pattern works in every browser shipped since March 2017. The oklch palette is the only modern ingredient.

Techniques used in this demo

Search CodeFronts

Loading…