Grid Archetypes

Compare six real CSS Grid layouts (Holy Grail, Masonry, Magazine, Dashboard, Bento, and a standard sidebar split), adjust their spacing, and copy the markup and grid-template-areas CSS for the one that fits your page.

Layout Preview

Holy Grail archetype

ATELIER perspective | TAILWIND target
Header
Nav
Main Content
Sidebar
Footer
<div className="grid gap-[16px] p-[24px] grid-cols-[200px_minmax(0,1fr)_200px] grid-rows-[auto_1fr_auto] min-h-screen" style={{ gridTemplateAreas: '"header header header" "nav main side" "footer footer footer"' }}>
  <header className="p-4 border rounded shadow-sm flex items-center justify-center [grid-area:header]">Header</header>
  <nav className="p-4 border rounded shadow-sm flex items-center justify-center [grid-area:nav]">Nav</nav>
  <main className="p-4 border rounded shadow-sm flex items-center justify-center [grid-area:main]">Main Content</main>
  <aside className="p-4 border rounded shadow-sm flex items-center justify-center [grid-area:side]">Sidebar</aside>
  <footer className="p-4 border rounded shadow-sm flex items-center justify-center [grid-area:footer]">Footer</footer>
</div>
// Layout and child placement are expressed in the Tailwind classes above.

Choose by Content Structure

Holy Grail places navigation and a sidebar on either side of the main content, the classic header-nav-main-sidebar-footer shape most site layouts trace back to. Magazine keeps one sidebar beside a wide article column, closer to what a blog or news page actually needs. Bento gives a lead tile extra space among evenly sized ones, Dashboard repeats metric cards alongside a wider chart, and Sidebar Standard keeps a simple navigation-and-content split with nothing else competing for space.

Gap, Padding, and Export

Gap changes the space between grid items; Padding changes the space inside the outer container. Both use pixels. Tailwind exports JSX with utility classes, Vanilla CSS exports HTML and CSS built on grid-template-areas, and Styled Components exports JSX with a styled definition. Pick whichever matches how the rest of your project is already set up.

Why Masonry Uses Row Spans, Not a Masonry Value

CSS does have a proposed grid-template-rows: masonry value, but it isn't reliably supported across browsers yet. This archetype builds the same staggered-tile look with a technique that works everywhere today: a short, fixed grid-auto-rows unit, with each tile spanning enough rows to reach its intended height. It's a real trade-off: tile heights are fixed by the row-span number here, not measured from their actual content, but it's the version you can ship now instead of waiting on browser support.

Before Adding Real Content

Holy Grail and Sidebar Standard include fixed-width side columns, and Bento stays at four columns, and none of these collapse to a single column on their own. Add your own breakpoints for narrow screens before shipping any of them; a sidebar layout that's comfortable at desktop width usually needs to stack vertically well before it reaches phone width.

A worked example: naming areas without breaking them

Holy Grail's exported CSS looks like this:

.layout {
  display: grid;
  grid-template-areas: "header header header" "nav main side" "footer footer footer";
  grid-template-columns: 200px 1fr 200px;
  grid-template-rows: auto 1fr auto;
  gap: 16px;
}

Each quoted string in grid-template-areas is one row of the grid, and each word inside it is one column cell in that row. Repeating a word across cells, the way "header" fills all three columns in the first row, tells the grid to merge those cells into a single spanning area. A child element joins that area with grid-area: header, and the name has to match a word in the template string exactly, character for character, or the browser silently drops it into the next available spot in normal document order instead of raising an error.

That silent fallback is the actual failure mode people hit: rename a component's class from header to site-header without updating the CSS, and nothing breaks loudly. The element just stops participating in the named layout and stacks wherever the grid's automatic placement puts it, which can look like a completely unrelated bug if you're not looking at grid-template-areas at the time.

Why these archetypes use auto-fill, not auto-fit

Masonry and Dashboard both size their columns with repeat(auto-fill, minmax(240px, 1fr)) and repeat(auto-fill, minmax(280px, 1fr)). The minmax part sets each column's floor and ceiling: never narrower than the minimum, never wider than an equal share of the available space. The auto-fill part decides how many of those columns exist at all: as many as fit in the container at the minimum width, even if there isn't enough content to fill them.

The alternative keyword, auto-fit, only differs in what happens with leftover space: it collapses any columns that end up with no content into zero width and lets the remaining columns stretch to fill the gap. With auto-fill, a row of three cards in a grid sized for five columns leaves two empty, invisible tracks and the cards stay at their minmax width. With auto-fit, those same three cards would stretch wider to fill the whole row. Neither is more correct; it depends on whether a sparse row should look intentionally left-aligned (auto-fill) or should always fill the full width (auto-fit). Bento skips this decision entirely with a fixed repeat(4, 1fr), since a four-tile hero layout is meant to hold a specific number of tiles rather than reflow around an arbitrary count.

Related Tools