Lesson 20 of 32
CSS Grid in Practice
A full-page header/sidebar/main/footer layout with grid-template-areas, a responsive card grid using repeat(auto-fit, minmax()), and when to reach for grid versus flexbox.
The previous lesson introduced grid's individual tools. This lesson builds two real layouts you'll reuse constantly — a whole-page skeleton and a responsive card grid that needs no media queries — and then draws a clear line between when to reach for grid versus flexbox.
A full-page layout with grid-template-areas
This is the shape almost every content-heavy page eventually needs: a header across the top, a sidebar down one side, a main content area, and a footer across the bottom.
.page {
display: grid;
grid-template-columns: 220px 1fr;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
min-height: 100vh;
gap: 1rem;
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
.footer { grid-area: footer; }<div class="page">
<header class="header">Site header</header>
<nav class="sidebar">Sidebar navigation</nav>
<main class="main">Page content</main>
<footer class="footer">Footer</footer>
</div>Reading the grid-template-areas value tells you the whole page's shape at
a glance, without mentally tracing line numbers: header spans the full
width on its own row, sidebar and main share the middle row, footer spans
the full width again. min-height: 100vh makes the whole layout at least
as tall as the viewport, so the footer doesn't ride up against short content.
A responsive card grid with auto-fit and minmax()
This single line replaces what used to take several media queries' worth of manual breakpoints:
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1.5rem;
}Breaking down exactly what each piece does:
minmax(200px, 1fr)defines one track's size range: never smaller than 200px, but allowed to grow up to1fr— an equal share of whatever space is left once the minimum widths are satisfied.repeat(auto-fit, ...)repeats that track definition as many times as will actually fit in the container's current width, given each repetition needs at least 200px. On a wide screen that might fit five columns; on a narrow one, maybe one or two — recalculated automatically as the container resizes, with no explicit breakpoint written anywhere.- Because the maximum in
minmaxis1fr, whatever columns do fit also stretch to fill any leftover width evenly, so cards don't leave an awkward half-empty column at the edge.
The result: as the container narrows, columns don't shrink below 200px —
instead, the grid drops a column entirely and redistributes the width among
the ones that remain. That's the entire responsive behaviour, and it comes
from one declaration, not a chain of @media rules each hand-picking a
column count for a specific width.
Grid versus flexbox: the real rule of thumb
Both can build layouts, and there's real overlap in what each one can do, but the well-established way to decide which to reach for is about dimensionality:
- Grid is for two-dimensional layout — when you need to coordinate rows and columns together, as one structure. A page skeleton, a card grid, anything where both the horizontal and vertical arrangement matter at once.
- Flexbox is for one-dimensional layout — a single row or a single column of items, where you're really only reasoning about one axis at a time. A navbar, a button group, a list of tags.
In practice, real pages use both together, and that's not a compromise — it's the idiomatic way to build with either tool. Grid handles the page's overall skeleton (the header/sidebar/main/footer shape above), and flexbox handles the one-dimensional arrangements inside individual components sitting within that skeleton — the navbar inside the header, the row of buttons inside a card, the tag list inside the sidebar. Reaching for grid to center one row of icons, or reaching for flexbox to coordinate a whole page's rows and columns, both work against the tool's grain; each one is at its best solving the dimensionality it was built for.
Try it yourself
A full page skeleton built with grid-template-areas, and beneath it a
responsive card grid using repeat(auto-fit, minmax(180px, 1fr)) — resize
your browser window (or shrink the Playground) to watch the column count
recalculate with no media query anywhere in the CSS.
What to remember
grid-template-areasnames a full page's regions in ASCII-art form, andgrid-areaplaces each child into the region it belongs to.repeat(auto-fit, minmax(200px, 1fr))fits as many tracks as will satisfy the minimum width, then stretches them to fill any leftover space — one line replacing many hand-picked breakpoints.- Grid is for two-dimensional layout (rows and columns together); flexbox is for one-dimensional layout (a single row or column).
- Real pages typically use both: grid for the page skeleton, flexbox for the one-dimensional components living inside it.
Check yourself
4 questions · pass 3/4 to unlock Positioning
1.In repeat(auto-fit, minmax(200px, 1fr)), what does auto-fit actually control?
2.What does the 1fr in minmax(200px, 1fr) do once columns are placed?
3.What is the well-established rule of thumb for choosing grid versus flexbox?
4.In a typical real page, how do grid and flexbox usually coexist?
4 left to answer