Grid Practice Layouts
Build 6 real-world layouts — card grids, dashboards, magazine layouts, and a complete app shell.
1. Introduction
This final Grid lesson is a practical reference — 6 layouts you will build over and over as a frontend developer. Each one demonstrates the best Grid techniques for that particular use case.
Patterns covered:
- Responsive card grid (auto-fit pattern)
- Holy Grail page layout (template areas)
- Magazine layout (spanning items)
- Dashboard grid (mixed spans)
- Photo gallery (fixed rows + object-fit)
- 12-column layout system (like Bootstrap)
2. Pattern Reference
Pattern 1: Responsive Card Grid
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
gap: 24px;
}
/* No media queries needed — automatically responsive */
Pattern 2: Holy Grail (Template Areas)
.page {
display: grid;
grid-template-areas:
"header header"
"sidebar main "
"footer footer";
grid-template-columns: 260px 1fr;
grid-template-rows: 64px 1fr 56px;
min-height: 100vh;
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
.footer { grid-area: footer; }
@media (max-width: 768px) {
.page {
grid-template-areas: "header" "main" "sidebar" "footer";
grid-template-columns: 1fr;
}
}
Pattern 3: Magazine Layout
.magazine {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: minmax(200px, auto);
gap: 16px;
}
.feature { grid-column: span 2; grid-row: span 2; }
.wide { grid-column: span 4; }
.tall { grid-row: span 2; }
Pattern 4: Dashboard
.dashboard {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: 140px;
gap: 16px;
}
.kpi-main { grid-column: span 2; grid-row: span 2; }
.chart-wide{ grid-column: span 3; }
.table-full{ grid-column: span 4; grid-row: span 2; }
Pattern 5: Photo Gallery
.gallery {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: 220px;
gap: 8px;
grid-auto-flow: dense;
}
.gallery img { width: 100%; height: 100%; object-fit: cover; }
.gallery .wide { grid-column: span 2; }
.gallery .tall { grid-row: span 2; }
Pattern 6: 12-Column System
.grid-12 {
display: grid;
grid-template-columns: repeat(12, 1fr);
gap: 24px;
}
.col-1 { grid-column: span 1; }
.col-2 { grid-column: span 2; }
.col-3 { grid-column: span 3; }
.col-4 { grid-column: span 4; }
.col-6 { grid-column: span 6; }
.col-8 { grid-column: span 8; }
.col-12 { grid-column: span 12; }
3. Real World Example
- Pattern 1 — Product listings on every e-commerce site
- Pattern 2 — Gmail, Notion, VS Code, GitHub — all use this shell
- Pattern 3 — New York Times, Medium, editorial blogs
- Pattern 4 — Google Analytics, Stripe Dashboard, Vercel
- Pattern 5 — Unsplash, Pinterest, photography portfolios
- Pattern 6 — Traditional Bootstrap-style column layout
4. Full Code Example — App Shell
<!-- HTML -->
<div class="app">
<header class="app__header">
<div class="app__brand">MyApp</div>
<nav class="app__topnav">...</nav>
</header>
<nav class="app__sidebar">
<ul>...</ul>
</nav>
<main class="app__main">
<div class="dashboard">
<div class="kpi kpi--main">Revenue</div>
<div class="kpi">Orders</div>
<div class="kpi">Users</div>
<div class="kpi">Conversion</div>
<div class="chart chart--wide">Sales Chart</div>
<div class="panel panel--tall">Activity</div>
</div>
</main>
<footer class="app__footer">Footer</footer>
</div>
/* ===== APP SHELL ===== */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; padding: 0; }
body { font-family: 'Inter', sans-serif; }
.app {
display: grid;
grid-template-areas:
"header header"
"sidebar main "
"footer footer";
grid-template-columns: 240px 1fr;
grid-template-rows: 64px 1fr auto;
min-height: 100vh;
}
.app__header {
grid-area: header;
background: #1e293b;
color: white;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 24px;
position: sticky;
top: 0;
z-index: 10;
}
.app__sidebar {
grid-area: sidebar;
background: #f8fafc;
border-right: 1px solid #e2e8f0;
padding: 16px;
position: sticky;
top: 64px; /* below fixed header */
height: calc(100vh - 64px);
overflow-y: auto;
}
.app__main {
grid-area: main;
padding: 24px;
background: #f1f5f9;
overflow-y: auto;
}
.app__footer {
grid-area: footer;
background: #0f172a;
color: #94a3b8;
padding: 16px 24px;
font-size: 0.875rem;
}
/* ===== DASHBOARD INSIDE MAIN ===== */
.dashboard {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: 140px;
gap: 16px;
}
.kpi {
background: white;
border-radius: 12px;
padding: 24px;
border: 1px solid #e2e8f0;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.kpi--main { grid-column: span 2; grid-row: span 2; }
.chart--wide { grid-column: span 3; }
.panel--tall { grid-row: span 2; }
/* ===== RESPONSIVE ===== */
@media (max-width: 1024px) {
.app {
grid-template-areas:
"header"
"main"
"footer";
grid-template-columns: 1fr;
}
.app__sidebar { display: none; }
.dashboard { grid-template-columns: repeat(2, 1fr); }
.kpi--main { grid-column: span 2; }
.chart--wide { grid-column: span 2; }
}
@media (max-width: 600px) {
.dashboard { grid-template-columns: 1fr; }
.kpi--main, .chart--wide, .panel--tall {
grid-column: auto;
grid-row: auto;
}
}
5. Code Breakdown
- App shell with named areas
- The
grid-template-areasmakes the entire page structure readable. At a glance you can see: header spans full width, sidebar on left, main on right, footer spans full width. - Sticky sidebar with
top: 64px; height: calc(100vh - 64px) - The sidebar sticks below the header (64px offset). Its height is viewport height minus the header so it fills exactly to the bottom without extending past it.
overflow-y: autoadds a scrollbar if the nav links are too many. - Nested grid (dashboard inside main)
- The
.app__mainarea contains its own grid (.dashboard). This is a nested grid — the outer grid handles the page shell, the inner grid handles the content layout. Nesting grids is normal and expected. - Progressive responsive breakdown
- At 1024px: sidebar hidden, two-column dashboard. At 600px: single column, all spans reset. Using
grid-column: auto; grid-row: auto;removes explicit placement and returns items to auto-placement.
6. Common Mistakes
- Overcomplicating layouts with Grid when Flexbox is simpler. A single row of buttons or nav links does not need Grid. Know which tool to use when.
- Not resetting explicit placement in mobile media queries. Items with
grid-column: span 3will still span 3 columns in a 1-column mobile layout. Reset toautoat the breakpoint. - Forgetting subgrid for aligned inner grids. If you need inner grid items to align with outer grid lines, CSS
subgridis the proper solution (newer but well-supported). - Using Grid for navbars and single-row components. These are simpler with Flexbox. Grid is for two-dimensional layouts.
7. Best Practices
- Grid for structure, Flexbox for components.
- Use template areas for page shells — readable, responsive-friendly.
- Reset spans in mobile breakpoints —
grid-column: auto. - Use
auto-fit, minmax()for card grids — no media queries needed for basic responsiveness. - Use DevTools Grid Inspector — Firefox and Chrome both highlight grid lines, areas, and item placement visually.
8. Practice Exercise
Build each of the 6 patterns from scratch:
- Pattern 1: Responsive card grid with at least 8 cards — no media queries
- Pattern 2: Holy Grail with responsive mobile layout
- Pattern 3: Magazine with 1 featured, 1 wide, and 4 regular articles
- Pattern 5: Photo gallery with some landscape/portrait/large photos
9. Assignment — CSS Grid Capstone
Build a complete admin dashboard application using CSS Grid for all layout:
- App Shell: Header, left sidebar, main area, footer — all using template areas
- Dashboard Main Area: 4-column grid with:
- 4 KPI cards (equal width, 140px height)
- 1 large chart spanning 3 columns
- 1 activity panel spanning 1 column, 2 rows
- 1 table spanning all 4 columns
- Responsive: Tablet (2 columns), Mobile (1 column, sidebar hidden)
- Each KPI card styled with Flexbox internally
- No inline styles, no floats — Grid + Flexbox only
10. Interview Questions
Q1: How would you build a responsive card grid without media queries?
Answer: Use display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 24px;. The auto-fit creates as many columns as fit, and minmax(250px, 1fr) ensures each is at minimum 250px. As the viewport narrows, columns automatically wrap to new rows.
Q2: How do you combine Grid and Flexbox effectively?
Answer: Use Grid for the macro layout — the overall page structure with rows and columns. Use Flexbox for the micro layout — within individual components. For example: Grid for header/sidebar/main/footer placement, Flexbox for the items inside the navbar, inside each card, and for the button groups.
Q3: What is the CSS Grid Inspector and why is it useful?
Answer: Browser DevTools (Firefox and Chrome) include a Grid Inspector that overlays numbered grid lines, named areas, and item placements on the rendered page. It is invaluable for debugging — you can see exactly which lines exist, where auto-placed items land, and why a spanning item is not where you expected.
Q4: How do you handle a grid item that spans multiple columns at different breakpoints?
Answer: Set the spanning in the default CSS (e.g. grid-column: span 3 for desktop). In the mobile media query, override with grid-column: auto or grid-column: span 1 to remove the spanning and allow auto-placement. Always reset explicit placements at narrower breakpoints.
Q5: What is subgrid and when would you use it?
Answer: Subgrid (now well-supported) lets a grid item's children align to the outer grid's tracks instead of creating an independent grid. It is useful when you need card content to align across multiple cards — for example, card titles, body text, and footers aligning on the same grid lines across all cards in a row, regardless of content length.
11. Additional Resources
- CSS-Tricks — A Complete Guide to Grid (search "css-tricks complete guide grid")
- Grid Garden — cssgridgarden.com
- Grid by Example — gridbyexample.com
- Layoutit Grid — grid.layoutit.com (visual Grid builder)
- MDN — Subgrid (search "MDN CSS subgrid")