The Holy Grail Layout Is a Grid Job
A reader recently asked how to pull off the classic three-column “Holy Grail” layout in flexbox — the kind of page skeleton with a header, footer, two sidebars, and a main content area in the middle. But flexbox isn’t really the right tool there. You can force it — say by grouping the nav and article together in a wrapper — but it takes that kind of structural conceit to make it behave. CSS Grid, on the other hand, was designed for exactly this sort of page-level arrangement, and browser support for both approaches is effectively the same these days. Grid is the more direct fit.

Why It Was Ever Hard
The name goes back to an era when a layout this unassuming was genuinely awkward to build in CSS. The tricky part wasn’t so much placing the columns as making them equal height. Developers resorted to ugly workarounds: oversized negative margins paired with positive padding, or background images that faked continuous columns. Any technique that managed it earned the “holy grail” label. The specifics varied, but the usual challenge was a three-column layout with the main content in the middle and height-matching side columns.
Modern CSS makes that kind of thing routine. Grid handles both the structure and the equal-height behavior natively, without hacks.
The Grid Version
Setting the layout up in Grid is straightforward. Both grid-template-columns and grid-template-rows are declared explicitly, which lets you place each major site section exactly where you want it in the overall page shape. No nesting tricks required — the header, nav, article, sidebar, and footer are all direct grid items.
A Few Extra Touches Included
- 1px separators between areas: Give the grid container a background color and
gap: 1px;. The underlying background shows through the gap, which effectively draws clean hairlines between the sections. - Responsive fallback for small screens: The demo switches to a single column at a media query breakpoint. Some setups just flip the parent to
display: block;to disable Grid entirely. This one keepsdisplay: grid;, and instead resets thegrid-template-columnsandgrid-template-rows. That way thegapis preserved, and sections can still be reordered if desired. - The “body border” effect: A light padding between the
<body>and the grid wrapper creates a subtle frame around the whole layout. It’s worth using a wrapper for the grid rather than styling the body as the grid container, since third-party scripts that inject elements into the body won’t then interfere with the layout.



