Episode 1 — Fundamentals / 1.8 — CSS Layout Mastery
1.8.d — Combining Grid and Flex
In one sentence: Use Grid for the page-level skeleton (header, sidebar, main, footer) and Flexbox for component-level alignment inside those regions — this combination covers virtually every real-world layout.
Navigation: ← 1.8.c — CSS Grid · 1.8.e — Positioning →
1. The mental model
┌─────────────────────────────────────────┐
│ GRID controls the page skeleton │
│ │
│ ┌─────────────────────────────────┐ │
│ │ FLEX controls component layout │ │
│ │ (navbar items, card content, │ │
│ │ button groups, form rows) │ │
│ └─────────────────────────────────┘ │
│ │
└─────────────────────────────────────────┘
| Level | Tool | Why |
|---|---|---|
| Page layout (rows + columns) | Grid | 2D control over header, sidebar, main, footer |
| Component alignment (single axis) | Flexbox | 1D distribution of items within a region |
| Either | Your call | Some patterns work equally well in both |
This is not a hard rule — it is a default starting point that keeps your CSS predictable.
2. Real-world architecture
Header — Flexbox
The header is a single row of items: logo, nav links, actions. Flexbox excels here.
.header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 24px;
height: 64px;
}
.header nav {
display: flex;
gap: 20px;
}
Main content area — Grid
The page body divides into sidebar + content area — a 2D decision.
.page-body {
display: grid;
grid-template-columns: 260px 1fr;
gap: 24px;
}
Cards within grid — Flexbox
Each card is a vertical stack: image, title, description, action button pushed to the bottom.
.card {
display: flex;
flex-direction: column;
}
.card .body {
flex: 1; /* pushes the action to the bottom */
}
Footer — Flexbox or Grid
Footer columns often use flex with wrapping or grid with auto-fill.
.footer {
display: flex;
flex-wrap: wrap;
gap: 40px;
justify-content: space-between;
}
3. When to nest grid inside flex
Less common, but useful when a flex item itself needs a 2D layout.
Example: A dashboard widget that lives in a flex row but internally arranges stats in a grid.
.widget-row {
display: flex;
gap: 24px;
}
.widget {
flex: 1;
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: auto 1fr;
gap: 12px;
}
4. When to nest flex inside grid
The most common nesting pattern. Grid cells contain flex components.
Example: A product listing page.
/* Page-level grid */
.product-page {
display: grid;
grid-template-columns: 240px 1fr;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"header header"
"filters products"
"footer footer";
min-height: 100vh;
}
/* Product grid (grid inside a grid cell) */
.products {
grid-area: products;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
gap: 20px;
}
/* Each product card uses flex */
.product-card {
display: flex;
flex-direction: column;
}
.product-card .price-row {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: auto; /* pushes to bottom of card */
}
5. Complete page layout example
/* === Page shell: Grid === */
.app {
display: grid;
grid-template-columns: 240px 1fr;
grid-template-rows: 64px 1fr auto;
grid-template-areas:
"header header"
"sidebar main"
"sidebar footer";
min-height: 100vh;
}
.app-header { grid-area: header; }
.app-sidebar { grid-area: sidebar; }
.app-main { grid-area: main; }
.app-footer { grid-area: footer; }
/* === Header: Flex === */
.app-header {
display: flex;
align-items: center;
padding: 0 24px;
gap: 16px;
}
.app-header .logo { margin-right: auto; }
/* === Sidebar: Flex (vertical) === */
.app-sidebar {
display: flex;
flex-direction: column;
padding: 16px;
gap: 8px;
}
/* === Main content: Grid for card layout === */
.app-main {
padding: 24px;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 24px;
align-content: start;
}
/* === Cards: Flex (vertical stack) === */
.card {
display: flex;
flex-direction: column;
border-radius: 8px;
overflow: hidden;
}
.card .content { flex: 1; padding: 16px; }
.card .actions {
display: flex;
justify-content: flex-end;
gap: 8px;
padding: 12px 16px;
}
┌─────────────────────────────────────────────┐
│ [Logo] Search... [User] [Menu] │ ← Flex
├────────┬────────────────────────────────────┤
│ Home │ ┌──────┐ ┌──────┐ ┌──────┐ │
│ Dash │ │ Card │ │ Card │ │ Card │ │ ← Grid
│ Users │ │(flex)│ │(flex)│ │(flex)│ │ of
│ ··· │ └──────┘ └──────┘ └──────┘ │ Cards
│ │ ┌──────┐ ┌──────┐ │ (flex)
│ ↕ │ │ Card │ │ Card │ │
│ Flex │ └──────┘ └──────┘ │
├────────┴────────────────────────────────────┤
│ Footer │
└─────────────────────────────────────────────┘
Grid shell (rows + columns)
6. Decision flowchart
Need to lay things out?
│
├─ One direction (row OR column)?
│ └─ Flexbox
│
├─ Two directions (rows AND columns)?
│ └─ Grid
│
├─ Both? (page skeleton + component details)
│ └─ Grid for the skeleton, Flex for components
│
└─ Positioning an overlay/tooltip/badge?
└─ position: absolute/fixed (see 1.8.e)
7. Key takeaways
- Grid for structure, flex for content is the default starting point.
- Nesting flex inside grid cells is the most common real-world pattern.
- A complete page typically has 2–3 levels: grid shell → grid/flex regions → flex components.
- Neither tool replaces the other — they solve different problems and work best together.
Explain-It Challenge
Explain without notes:
- Why is the header typically flex while the page body is grid?
- How would you ensure all cards in a grid row have their action buttons aligned at the bottom?
- Draw (or describe) the nesting of grid and flex in a typical e-commerce product listing page.
Navigation: ← 1.8.c — CSS Grid · 1.8.e — Positioning →