12 CSS Grid Layout Patterns You'll Use in Every Project
From holy grail layouts to magazine-style grids — 12 battle-tested CSS Grid patterns with clean, copy-paste code. Includes responsive variants for each.
CSS Grid unlocked layouts that used to require JavaScript or complex float hacks. After years of browser support, there's now a set of patterns that come up again and again — worth having committed to muscle memory.
Header, sidebar, main content, and footer — the classic web layout:
body {
display: grid;
grid-template:
"header header " 60px
"sidebar main " 1fr
"footer footer " auto
/ 240px 1fr;
min-height: 100dvh;
gap: 0;
}
header { grid-area: header; }
aside { grid-area: sidebar; }
main { grid-area: main; }
footer { grid-area: footer; }
Cards that automatically wrap based on available space — no media queries needed:
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 1.5rem;
}
auto-fill creates as many columns as fit. minmax(280px, 1fr) means each column is at least 280px but can grow. The result: 4 columns on a wide screen, 1 column on mobile — zero media queries.
.content-grid {
display: grid;
grid-template-columns:
1fr
min(65ch, 100% - 3rem)
1fr;
}
.content-grid > * { grid-column: 2; }
.full-bleed { grid-column: 1 / -1; }
Everything inside sits in a comfortable reading width. Add .full-bleed to images or banners that should stretch edge to edge.
CSS Grid doesn't natively support masonry (variable-height rows), but you can fake it with dense auto-placement:
.masonry {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
grid-auto-rows: 10px;
gap: 12px 16px;
}
/* Each item sets its own row span via JS or inline style */
.masonry-item {
grid-row: span calc(var(--height) / 10);
}
.with-sidebar {
display: grid;
grid-template-columns: 300px 1fr;
gap: 2rem;
align-items: start; /* Essential for sticky to work */
}
aside {
position: sticky;
top: 80px; /* Account for fixed nav */
}
The align-items: start is critical. Without it, the sidebar stretches to the height of main content and sticky has nothing to scroll against.