How to use this course
One new idea at a time
Do not read ten properties and try to remember them. At each stage: read the idea, predict the result, open the full code, paste it into the editor, then change exactly one value. The lesson deliberately repeats simple boxes so your attention stays on layout.
Every step contains
- One concept
- Smallest useful code
- Result to expect
- A change-it-yourself task
- Complete runnable HTML
- Link back to the embedded editor
HTML, CSS, boxes, parents and normal flowPhase BFlexbox Foundations
One-dimensional layout from first line to mini-projectPhase CGrid Foundations
Rows, columns, responsive tracks and named areasPhase DResponsive Real Layouts
Media queries, nesting, page shells and dashboardsPhase EAdvanced + Debugging
Overflow, content sizing, fluid design, subgrid and accessibilityPhase FInfinity Project
Design from a layout plan instead of memorising properties
Your laboratory
Embedded HTML editor
Open a stage’s “Full runnable HTML”, copy it, paste it here, run it, and then complete the “Change this” task. You can also open the editor separately.
Open editor in a new tabPhase A
Absolute Zero
HTML, CSS, boxes, parents and normal flow
Phase A · Step 0
What are HTML and CSS?
HTML creates the things. CSS changes how they look and where they sit.
Smallest useful code
<h1>Hello</h1>
<p>This is HTML.</p>What you should see
Run the full example below for the exact result. The diagram is only a mental model.
Full runnable HTML for Step 0 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 0: What are HTML and CSS?</title>
<style>
body { font-family: Arial, sans-serif; padding: 24px; }
h1 { color: #0b67b2; }
</style>
</head>
<body>
<h1>Hello</h1>
<p>This is HTML. CSS makes the heading blue.</p>
</body>
</html>Phase A · Step 1
Make your first box with A
is a general-purpose container.
A container can hold text or other elements. Layout becomes easier when you learn to see a page as containers inside containers.
Smallest useful code
<div>My first box</div>
What you should see
Parent / layoutChild AChild B
Run the full example below for the exact result. The diagram is only a mental model.
Change this: Add a second . Notice where it appears before using Flexbox or Grid.
Full runnable HTML for Step 1 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 1: Make your first box with <div></title>
<style>
body { font-family: Arial, sans-serif; padding: 24px; }
div { border: 2px solid #0b67b2; padding: 20px; }
</style>
</head>
<body>
<div>My first box</div>
</body>
</html>
2Phase A · Step 2
Give boxes classes
A class gives a reusable name to one or more elements.
Instead of styling every div, name the kind of box you want. CSS classes begin with a dot.
Smallest useful code
<div class="box">A</div>
<div class="box">B</div>
What you should see
Parent / layoutChild AChild B
Run the full example below for the exact result. The diagram is only a mental model.
Change this: Rename class="box" to class="card" in both HTML and CSS.
Full runnable HTML for Step 2 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 2: Give boxes classes</title>
<style>
body {
margin: 0;
padding: 24px;
font-family: Arial, sans-serif;
background: #f5f8fb;
color: #203040;
}
.box {
padding: 18px;
border: 2px solid #0b67b2;
border-radius: 10px;
background: white;
text-align: center;
font-weight: bold;
}
</style>
</head>
<body>
<div class="box">A</div>
<br>
<div class="box">B</div>
</body>
</html>
3Phase A · Step 3
Understand width, padding, border and margin
Every element is a rectangular box.
Content sits inside padding, padding sits inside the border, and margin creates space outside the border. This is the box model.
Smallest useful code
.box {
width: 220px;
padding: 20px;
border: 4px solid #0b67b2;
margin: 20px;
}
What you should see
Parent / layoutChild AChild B
Run the full example below for the exact result. The diagram is only a mental model.
Change this: Change padding from 20px to 50px. Then change margin to 0.
Full runnable HTML for Step 3 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 3: Understand width, padding, border and margin</title>
<style>
body { font-family: Arial, sans-serif; }
.box { width:220px; padding:20px; border:4px solid #0b67b2; margin:20px; background:#fff; }
</style>
</head>
<body>
<div class="box">Content → padding → border → margin</div>
</body>
</html>
4Phase A · Step 4
Parent and children
Flexbox and Grid are usually applied to a parent.
The parent controls the layout of its direct children. This is the single most important relationship in this course.
Smallest useful code
<div class="parent">
<div class="child">A</div>
<div class="child">B</div>
<div class="child">C</div>
</div>
What you should see
Parent / layoutChild AChild B
Run the full example below for the exact result. The diagram is only a mental model.
Change this: Add a fourth child. Do not add any Flexbox yet.
Full runnable HTML for Step 4 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 4: Parent and children</title>
<style>
body { font-family:Arial,sans-serif; padding:24px; }
.parent { border:3px dashed #7997ad; padding:12px; }
.child { border:2px solid #0b67b2; padding:14px; margin:8px 0; }
</style>
</head>
<body>
<div class="parent">
<div class="child">A</div>
<div class="child">B</div>
<div class="child">C</div>
</div>
</body>
</html>
5Phase A · Step 5
See normal document flow
Block elements naturally stack vertically.
Before layout CSS, divs usually take available width and appear one below another. Flexbox/Grid deliberately change this arrangement.
Smallest useful code
.parent { border: 3px dashed #7997ad; }
.child { padding: 16px; border: 2px solid #0b67b2; }
What you should see
Parent / layoutChild AChild B
Run the full example below for the exact result. The diagram is only a mental model.
Change this: Predict what will happen when the parent becomes display:flex in the next stage.
Full runnable HTML for Step 5 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 5: See normal document flow</title>
<style>
body { font-family:Arial,sans-serif; padding:24px; }
.parent { border:3px dashed #7997ad; padding:12px; }
.child { padding:16px; border:2px solid #0b67b2; background:white; }
</style>
</head>
<body>
<div class="parent">
<div class="child">One</div>
<div class="child">Two</div>
<div class="child">Three</div>
</div>
</body>
</html>
Phase B
Flexbox Foundations
One-dimensional layout from first line to mini-project
6Phase B · Step 6
Your first Flexbox
One line changes the children from normal block flow into flex items.
Apply display:flex to the parent—not to every child. The direct children become flex items.
Smallest useful code
.parent {
display: flex;
}
What you should see
Parent / layoutChild AChild B
Run the full example below for the exact result. The diagram is only a mental model.
Change this: Remove display:flex, run it, then put it back. Compare.
Full runnable HTML for Step 6 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 6: Your first Flexbox</title>
<style>
body { font-family:Arial,sans-serif; padding:24px; }
.parent { display:flex; border:3px dashed #7997ad; padding:12px; }
.child { padding:16px; border:2px solid #0b67b2; background:white; }
</style>
</head>
<body>
<div class="parent">
<div class="child">One</div>
<div class="child">Two</div>
<div class="child">Three</div>
</div>
</body>
</html>
7Phase B · Step 7
Main axis and cross axis
Flexbox always has a main axis and a cross axis.
With the default flex-direction:row, the main axis runs left→right and the cross axis runs top→bottom. justify-content works on the main axis; align-items works on the cross axis.
Smallest useful code
.parent {
display: flex;
/* main axis → */
/* cross axis ↓ */
}
What you should see
Parent / layoutChild AChild B
Run the full example below for the exact result. The diagram is only a mental model.
Change this: Keep this axis idea in mind. It explains most Flexbox properties.
Full runnable HTML for Step 7 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 7: Main axis and cross axis</title>
<style>
body {font-family:Arial,sans-serif;padding:24px}.parent{display:flex;min-height:180px;border:3px dashed #7997ad;padding:12px}.child{padding:16px;border:2px solid #0b67b2;background:white}
</style>
</head>
<body>
<div class="parent">
<div class="child">A</div>
<div class="child">B</div>
<div class="child">C</div>
</div>
</body>
</html>
8Phase B · Step 8
Change flex direction
flex-direction chooses the main axis.
row is horizontal. column is vertical. row-reverse and column-reverse reverse the visual direction.
Smallest useful code
.parent {
display: flex;
flex-direction: column;
}
What you should see
Parent / layoutChild AChild B
Run the full example below for the exact result. The diagram is only a mental model.
Change this: Try row, column, row-reverse and column-reverse one by one.
Full runnable HTML for Step 8 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 8: Change flex direction</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.parent{display:flex;flex-direction:column;gap:10px;border:3px dashed #7997ad;padding:12px}.child{padding:16px;border:2px solid #0b67b2;background:white}
</style>
</head>
<body>
<div class="parent"><div class="child">A</div><div class="child">B</div><div class="child">C</div></div>
</body>
</html>
9Phase B · Step 9
Add clean spacing with gap
gap creates space between flex items without outside-edge margin problems.
For modern Flexbox, gap is usually simpler than putting margin on every child.
Smallest useful code
.parent {
display: flex;
gap: 16px;
}
What you should see
Parent / layoutChild AChild B
Run the full example below for the exact result. The diagram is only a mental model.
Change this: Try gap:0, gap:8px, gap:32px.
Full runnable HTML for Step 9 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 9: Add clean spacing with gap</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.parent{display:flex;gap:16px;border:3px dashed #7997ad;padding:12px}.child{padding:16px;border:2px solid #0b67b2;background:white}
</style>
</head>
<body>
<div class="parent"><div class="child">A</div><div class="child">B</div><div class="child">C</div></div>
</body>
</html>
10Phase B · Step 10
Move items along the main axis
justify-content distributes free space on the main axis.
Common values are flex-start, center, flex-end, space-between, space-around and space-evenly.
Smallest useful code
.parent {
display: flex;
justify-content: space-between;
}
What you should see
Parent / layoutChild AChild B
Run the full example below for the exact result. The diagram is only a mental model.
Change this: Test all six common justify-content values.
Full runnable HTML for Step 10 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 10: Move items along the main axis</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.parent{display:flex;justify-content:space-between;gap:10px;border:3px dashed #7997ad;padding:12px}.child{padding:16px;border:2px solid #0b67b2;background:white}
</style>
</head>
<body>
<div class="parent"><div class="child">A</div><div class="child">B</div><div class="child">C</div></div>
</body>
</html>
11Phase B · Step 11
Move items along the cross axis
align-items aligns flex items on the cross axis.
To see vertical alignment in a row, the parent needs extra height.
Smallest useful code
.parent {
display: flex;
min-height: 220px;
align-items: center;
}
What you should see
Parent / layoutChild AChild B
Run the full example below for the exact result. The diagram is only a mental model.
Change this: Try flex-start, center, flex-end and stretch.
Full runnable HTML for Step 11 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 11: Move items along the cross axis</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.parent{display:flex;min-height:220px;align-items:center;gap:10px;border:3px dashed #7997ad;padding:12px}.child{padding:16px;border:2px solid #0b67b2;background:white}
</style>
</head>
<body>
<div class="parent"><div class="child">Short</div><div class="child">Medium box</div><div class="child">Tall?</div></div>
</body>
</html>
12Phase B · Step 12
Center something both ways
Combine justify-content and align-items.
This is the classic “center a box” Flexbox pattern.
Smallest useful code
.parent {
display: flex;
justify-content: center;
align-items: center;
min-height: 300px;
}
What you should see
Parent / layoutChild AChild B
Run the full example below for the exact result. The diagram is only a mental model.
Change this: Change justify-content only. Then restore center and change align-items only.
Full runnable HTML for Step 12 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 12: Center something both ways</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.parent{display:flex;justify-content:center;align-items:center;min-height:300px;border:3px dashed #7997ad}.child{padding:24px;border:2px solid #0b67b2;background:white;border-radius:10px}
</style>
</head>
<body>
<div class="parent"><div class="child">Perfectly centered</div></div>
</body>
</html>
13Phase B · Step 13
Allow items to wrap
flex-wrap lets items move to another line when space runs out.
Without wrapping, Flexbox tries to keep items on one line and may shrink them.
Smallest useful code
.parent {
display: flex;
flex-wrap: wrap;
gap: 12px;
}
.child { width: 180px; }
What you should see
Parent / layoutChild AChild B
Run the full example below for the exact result. The diagram is only a mental model.
Change this: Resize the browser. Then remove flex-wrap and compare.
Full runnable HTML for Step 13 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 13: Allow items to wrap</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.parent{display:flex;flex-wrap:wrap;gap:12px;border:3px dashed #7997ad;padding:12px}.child{width:180px;padding:16px;border:2px solid #0b67b2;background:white}
</style>
</head>
<body>
<div class="parent"><div class="child">Item 1</div><div class="child">Item 2</div><div class="child">Item 3</div><div class="child">Item 4</div><div class="child">Item 5</div><div class="child">Item 6</div></div>
</body>
</html>
14Phase B · Step 14
Choose a starting size with flex-basis
flex-basis is the preferred main-axis starting size.
It is often more useful than width inside a flexible row.
Smallest useful code
.child {
flex-basis: 180px;
}
What you should see
Parent / layoutChild AChild B
Run the full example below for the exact result. The diagram is only a mental model.
Change this: Try flex-basis:120px and 250px. Watch when wrapping occurs.
Full runnable HTML for Step 14 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 14: Choose a starting size with flex-basis</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.parent{display:flex;flex-wrap:wrap;gap:12px}.child{flex-basis:180px;padding:16px;border:2px solid #0b67b2;background:white}
</style>
</head>
<body>
<div class="parent"><div class="child">Card 1</div><div class="child">Card 2</div><div class="child">Card 3</div><div class="child">Card 4</div><div class="child">Card 5</div></div>
</body>
</html>
15Phase B · Step 15
Let items grow
flex-grow decides how leftover space is shared.
A grow value of 2 asks an item to receive twice the share of leftover space compared with an item whose grow value is 1.
Smallest useful code
.a { flex-grow: 1; }
.b { flex-grow: 2; }
.c { flex-grow: 1; }
What you should see
Parent / layoutChild AChild B
Run the full example below for the exact result. The diagram is only a mental model.
Change this: Set B to flex-grow:5. Explain the result in your own words.
Full runnable HTML for Step 15 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 15: Let items grow</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.parent{display:flex;gap:10px}.child{padding:16px;border:2px solid #0b67b2;background:white}.a,.c{flex-grow:1}.b{flex-grow:2}
</style>
</head>
<body>
<div class="parent"><div class="child a">1 share</div><div class="child b">2 shares</div><div class="child c">1 share</div></div>
</body>
</html>
16Phase B · Step 16
Control shrinking
flex-shrink decides how items give up space when there is not enough room.
Use flex-shrink:0 when an item should resist shrinking, but be careful: it can force overflow.
Smallest useful code
.fixed {
width: 240px;
flex-shrink: 0;
}
What you should see
Parent / layoutChild AChild B
Run the full example below for the exact result. The diagram is only a mental model.
Change this: Remove flex-shrink:0. Then make both items non-shrinking and observe overflow.
Full runnable HTML for Step 16 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 16: Control shrinking</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.parent{display:flex;gap:10px;width:420px;max-width:100%;border:3px dashed #7997ad}.child{width:240px;padding:16px;border:2px solid #0b67b2;background:white}.fixed{flex-shrink:0}
</style>
</head>
<body>
<div class="parent"><div class="child fixed">I do not shrink</div><div class="child">I can shrink</div></div>
</body>
</html>
17Phase B · Step 17
Use the flex shorthand
flex combines grow, shrink and basis.
flex:1 is a common way to make siblings share available space. flex:1 1 200px means grow, shrink and start around 200px.
Smallest useful code
.child {
flex: 1 1 200px;
}
What you should see
Parent / layoutChild AChild B
Run the full example below for the exact result. The diagram is only a mental model.
Change this: Change 200px to 300px. Resize the page and watch the breakpoints happen naturally.
Full runnable HTML for Step 17 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 17: Use the flex shorthand</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.parent{display:flex;flex-wrap:wrap;gap:12px}.child{flex:1 1 200px;padding:16px;border:2px solid #0b67b2;background:white}
</style>
</head>
<body>
<div class="parent"><div class="child">Flexible 1</div><div class="child">Flexible 2</div><div class="child">Flexible 3</div><div class="child">Flexible 4</div></div>
</body>
</html>
18Phase B · Step 18
Override one item with align-self
align-self changes cross-axis alignment for one flex item.
The parent may align every item one way while a special child opts out.
Smallest useful code
.parent { align-items: flex-start; }
.special { align-self: flex-end; }
What you should see
Parent / layoutChild AChild B
Run the full example below for the exact result. The diagram is only a mental model.
Change this: Try align-self:center and stretch.
Full runnable HTML for Step 18 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 18: Override one item with align-self</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.parent{display:flex;align-items:flex-start;min-height:220px;gap:10px;border:3px dashed #7997ad}.child{padding:16px;border:2px solid #0b67b2;background:white}.special{align-self:flex-end}
</style>
</head>
<body>
<div class="parent"><div class="child">A</div><div class="child special">Special</div><div class="child">C</div></div>
</body>
</html>
19Phase B · Step 19
Visual order and source order
order can visually rearrange flex items, but it does not rewrite the document’s logical order.
Use order sparingly. Keyboard and screen-reader order can still follow the HTML source, so important reading order should usually stay meaningful in the markup.
Smallest useful code
.first-visually { order: -1; }
What you should see
Parent / layoutChild AChild B
Run the full example below for the exact result. The diagram is only a mental model.
Change this: Remove order. Then move the element in the HTML instead and compare the idea.
Important: Prefer meaningful HTML order; use CSS order only when there is a strong reason.
Full runnable HTML for Step 19 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 19: Visual order and source order</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.parent{display:flex;gap:10px}.child{padding:16px;border:2px solid #0b67b2;background:white}.first-visually{order:-1}
</style>
</head>
<body>
<div class="parent"><div class="child">HTML first</div><div class="child">HTML second</div><div class="child first-visually">HTML third, visual first</div></div>
</body>
</html>
20Phase B · Step 20
Flexbox mini-project: navigation bar
A navbar is a natural one-dimensional layout.
Use Flexbox for the outer bar and again for the link group. This is your first nested flex layout.
Smallest useful code
.nav {
display:flex;
justify-content:space-between;
align-items:center;
gap:16px;
flex-wrap:wrap;
}
.links { display:flex; gap:12px; }
What you should see
Parent / layoutChild AChild B
Run the full example below for the exact result. The diagram is only a mental model.
Change this: Add two more links. Then use margin-left:auto on the links and see another common navbar pattern.
Full runnable HTML for Step 20 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 20: Flexbox mini-project: navigation bar</title>
<style>
body{margin:0;font-family:Arial,sans-serif}.nav{display:flex;justify-content:space-between;align-items:center;gap:16px;flex-wrap:wrap;padding:16px 24px;background:#0b67b2;color:white}.brand{font-weight:bold;font-size:1.25rem}.links{display:flex;gap:12px;flex-wrap:wrap}.links a{color:white;text-decoration:none;padding:8px 10px;background:rgba(255,255,255,.12);border-radius:8px}
</style>
</head>
<body>
<nav class="nav"><div class="brand">Learn With Champak</div><div class="links"><a href="#">Home</a><a href="#">Lessons</a><a href="#">Practice</a></div></nav>
</body>
</html>
Phase C
Grid Foundations
Rows, columns, responsive tracks and named areas
21Phase C · Step 21
Your first CSS Grid
display:grid turns direct children into grid items.
Grid does not become visibly “grid-like” until you define tracks such as columns or rows.
Smallest useful code
.parent {
display: grid;
grid-template-columns: 1fr 1fr;
}
What you should see
Parent / layoutChild AChild B
Run the full example below for the exact result. The diagram is only a mental model.
Change this: Change two columns to three: 1fr 1fr 1fr.
Full runnable HTML for Step 21 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 21: Your first CSS Grid</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.parent{display:grid;grid-template-columns:1fr 1fr;gap:10px}.child{padding:18px;border:2px solid #0b67b2;background:white}
</style>
</head>
<body>
<div class="parent"><div class="child">A</div><div class="child">B</div><div class="child">C</div><div class="child">D</div></div>
</body>
</html>
22Phase C · Step 22
Make columns with fixed units
grid-template-columns defines the column tracks.
Start with explicit pixel widths so the track idea is obvious.
Smallest useful code
.grid {
display:grid;
grid-template-columns: 150px 250px;
}
What you should see
Parent / layoutChild AChild B
Run the full example below for the exact result. The diagram is only a mental model.
Change this: Try 100px 300px, then 200px 200px. Notice fixed tracks do not care about available width.
Full runnable HTML for Step 22 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 22: Make columns with fixed units</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.grid{display:grid;grid-template-columns:150px 250px;gap:10px;max-width:100%}.item{padding:18px;border:2px solid #0b67b2;background:white}
</style>
</head>
<body>
<div class="grid"><div class="item">150px column</div><div class="item">250px column</div></div>
</body>
</html>
23Phase C · Step 23
Meet the fr unit
fr means a fraction of the available grid space.
1fr 1fr creates equal flexible columns. 1fr 2fr gives the second column roughly twice the share of remaining space.
Smallest useful code
.grid {
display:grid;
grid-template-columns: 1fr 2fr;
gap:12px;
}
What you should see
Parent / layoutChild AChild B
Run the full example below for the exact result. The diagram is only a mental model.
Change this: Try 1fr 1fr 1fr and then 2fr 1fr 1fr.
Full runnable HTML for Step 23 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 23: Meet the fr unit</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.grid{display:grid;grid-template-columns:1fr 2fr;gap:12px}.item{padding:18px;border:2px solid #0b67b2;background:white}
</style>
</head>
<body>
<div class="grid"><div class="item">1fr</div><div class="item">2fr</div></div>
</body>
</html>
24Phase C · Step 24
Stop repeating yourself with repeat()
repeat() writes repeated tracks more clearly.
repeat(4,1fr) means four equal flexible columns.
Smallest useful code
.grid {
display:grid;
grid-template-columns: repeat(4, 1fr);
}
What you should see
Parent / layoutChild AChild B
Run the full example below for the exact result. The diagram is only a mental model.
Change this: Change 4 to 2, 3 and 5.
Full runnable HTML for Step 24 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 24: Stop repeating yourself with repeat()</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.grid{display:grid;grid-template-columns:repeat(4,1fr);gap:10px}.item{padding:18px;border:2px solid #0b67b2;background:white}
</style>
</head>
<body>
<div class="grid"><div class="item">1</div><div class="item">2</div><div class="item">3</div><div class="item">4</div><div class="item">5</div><div class="item">6</div><div class="item">7</div><div class="item">8</div></div>
</body>
</html>
25Phase C · Step 25
Rows and gap
Grid has both column tracks and row tracks.
Rows can be explicit with grid-template-rows, or they can be created automatically as more items are placed.
Smallest useful code
.grid {
display:grid;
grid-template-columns: repeat(3,1fr);
grid-template-rows: 80px 140px;
gap:12px;
}
What you should see
Parent / layoutChild AChild B
Run the full example below for the exact result. The diagram is only a mental model.
Change this: Change the first row from 80px to auto. Compare.
Full runnable HTML for Step 25 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 25: Rows and gap</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.grid{display:grid;grid-template-columns:repeat(3,1fr);grid-template-rows:80px 140px;gap:12px}.item{padding:18px;border:2px solid #0b67b2;background:white}
</style>
</head>
<body>
<div class="grid"><div class="item">1</div><div class="item">2</div><div class="item">3</div><div class="item">4</div><div class="item">5</div><div class="item">6</div></div>
</body>
</html>
26Phase C · Step 26
Align content inside grid cells
place-items is shorthand for align-items and justify-items.
Unlike Flexbox alignment, Grid can align each item inside its own cell in two dimensions.
Smallest useful code
.grid {
display:grid;
grid-template-columns:repeat(3,1fr);
grid-auto-rows:120px;
place-items:center;
}
What you should see
Parent / layoutChild AChild B
Run the full example below for the exact result. The diagram is only a mental model.
Change this: Try place-items:start, end, stretch and center.
Full runnable HTML for Step 26 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 26: Align content inside grid cells</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.grid{display:grid;grid-template-columns:repeat(3,1fr);grid-auto-rows:120px;place-items:center;gap:10px;border:3px dashed #7997ad}.item{padding:18px;border:2px solid #0b67b2;background:white}
</style>
</head>
<body>
<div class="grid"><div class="item">A</div><div class="item">B</div><div class="item">C</div></div>
</body>
</html>
27Phase C · Step 27
Let Grid auto-place items
Grid automatically fills cells in source order unless you tell an item to go somewhere special.
This automatic placement makes ordinary card collections very easy.
Smallest useful code
.grid {
display:grid;
grid-template-columns:repeat(3,1fr);
gap:12px;
}
What you should see
Parent / layoutChild AChild B
Run the full example below for the exact result. The diagram is only a mental model.
Change this: Add Card 8 and Card 9. Predict which row and column each one gets.
Full runnable HTML for Step 27 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 27: Let Grid auto-place items</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.grid{display:grid;grid-template-columns:repeat(3,1fr);gap:12px}.item{padding:18px;border:2px solid #0b67b2;background:white}
</style>
</head>
<body>
<div class="grid"><div class="item">Card 1</div><div class="item">Card 2</div><div class="item">Card 3</div><div class="item">Card 4</div><div class="item">Card 5</div><div class="item">Card 6</div><div class="item">Card 7</div></div>
</body>
</html>
28Phase C · Step 28
Give tracks limits with minmax()
minmax(min,max) lets a track stay within useful limits.
This is one of the keys to responsive Grid. A card can have a minimum width but still grow when room exists.
Smallest useful code
.grid {
display:grid;
grid-template-columns:repeat(3, minmax(140px, 1fr));
}
What you should see
Parent / layoutChild AChild B
Run the full example below for the exact result. The diagram is only a mental model.
Change this: Change 140px to 220px. What happens on a narrow screen?
Full runnable HTML for Step 28 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 28: Give tracks limits with minmax()</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.grid{display:grid;grid-template-columns:repeat(3,minmax(140px,1fr));gap:12px}.item{padding:18px;border:2px solid #0b67b2;background:white}
</style>
</head>
<body>
<div class="grid"><div class="item">Card 1</div><div class="item">Card 2</div><div class="item">Card 3</div><div class="item">Card 4</div><div class="item">Card 5</div><div class="item">Card 6</div></div>
</body>
</html>
29Phase C · Step 29
Responsive cards with auto-fit
auto-fit lets the browser choose how many tracks fit.
repeat(auto-fit,minmax(180px,1fr)) is a powerful responsive card pattern that often needs no media query.
Smallest useful code
.grid {
display:grid;
grid-template-columns:repeat(auto-fit, minmax(180px, 1fr));
gap:16px;
}
What you should see
Parent / layoutChild AChild B
Run the full example below for the exact result. The diagram is only a mental model.
Change this: Resize continuously. Count how many columns appear at different widths.
Full runnable HTML for Step 29 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 29: Responsive cards with auto-fit</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:16px}.item{padding:24px;border:2px solid #0b67b2;background:white}
</style>
</head>
<body>
<div class="grid"><div class="item">Responsive 1</div><div class="item">Responsive 2</div><div class="item">Responsive 3</div><div class="item">Responsive 4</div><div class="item">Responsive 5</div><div class="item">Responsive 6</div><div class="item">Responsive 7</div><div class="item">Responsive 8</div></div>
</body>
</html>
30Phase C · Step 30
Make an item span columns
A grid item can occupy more than one track.
grid-column:span 2 means “use two column tracks from wherever I am auto-placed.”
Smallest useful code
.wide {
grid-column: span 2;
}
What you should see
Parent / layoutChild AChild B
Run the full example below for the exact result. The diagram is only a mental model.
Change this: Make the wide item span 3. Then try span 4.
Full runnable HTML for Step 30 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 30: Make an item span columns</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.grid{display:grid;grid-template-columns:repeat(4,1fr);gap:10px}.item{padding:18px;border:2px solid #0b67b2;background:white}.wide{grid-column:span 2}
</style>
</head>
<body>
<div class="grid"><div class="item wide">I span 2 columns</div><div class="item">B</div><div class="item">C</div><div class="item">D</div><div class="item">E</div></div>
</body>
</html>
31Phase C · Step 31
Place items using grid lines
Grid tracks are separated by numbered lines.
grid-column:1 / -1 means start at the first column line and finish at the final line—useful for full-width headers.
Smallest useful code
.header {
grid-column: 1 / -1;
}
What you should see
Parent / layoutChild AChild B
Run the full example below for the exact result. The diagram is only a mental model.
Change this: Change the header to grid-column:1 / 3 and identify the lines.
Full runnable HTML for Step 31 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 31: Place items using grid lines</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.grid{display:grid;grid-template-columns:repeat(3,1fr);gap:10px}.item{padding:18px;border:2px solid #0b67b2;background:white}.header{grid-column:1 / -1;background:#e8f5ff}
</style>
</head>
<body>
<div class="grid"><div class="item header">Full-width header</div><div class="item">A</div><div class="item">B</div><div class="item">C</div></div>
</body>
</html>
32Phase C · Step 32
Name page regions with grid-template-areas
Named areas make page-shell CSS readable.
Instead of remembering line numbers, give regions names such as header, sidebar, main and footer.
Smallest useful code
.page {
display:grid;
grid-template-columns:220px 1fr;
grid-template-areas:
"header header"
"side main"
"footer footer";
}
header { grid-area:header; }
What you should see
Parent / layoutChild AChild B
Run the full example below for the exact result. The diagram is only a mental model.
Change this: Swap the sidebar and main names in grid-template-areas and observe the visual change.
Full runnable HTML for Step 32 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 32: Name page regions with grid-template-areas</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.page{display:grid;grid-template-columns:220px 1fr;grid-template-areas:"header header" "side main" "footer footer";gap:10px}.region{padding:22px;border:2px solid #0b67b2;background:white}.head{grid-area:header}.side{grid-area:side}.main{grid-area:main}.foot{grid-area:footer}
</style>
</head>
<body>
<div class="page"><header class="region head">Header</header><aside class="region side">Sidebar</aside><main class="region main">Main</main><footer class="region foot">Footer</footer></div>
</body>
</html>
33Phase C · Step 33
Grid mini-project: responsive gallery
A gallery is a natural repeated two-dimensional layout.
Use auto-fit + minmax so the gallery adapts from many columns to one column without many breakpoints.
Smallest useful code
.gallery {
display:grid;
grid-template-columns:repeat(auto-fit,minmax(160px,1fr));
gap:14px;
}
What you should see
Parent / layoutChild AChild B
Run the full example below for the exact result. The diagram is only a mental model.
Change this: Change minmax(160px,1fr) to 240px. Decide which minimum feels better.
Full runnable HTML for Step 33 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 33: Grid mini-project: responsive gallery</title>
<style>
body{font-family:Arial,sans-serif;padding:24px;background:#f5f8fb}.gallery{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:14px}.photo{aspect-ratio:4/3;display:grid;place-items:center;border-radius:12px;background:linear-gradient(135deg,#dff1ff,#fff);border:2px solid #0b67b2;font-weight:bold}
</style>
</head>
<body>
<div class="gallery"><div class="photo">Photo 1</div><div class="photo">Photo 2</div><div class="photo">Photo 3</div><div class="photo">Photo 4</div><div class="photo">Photo 5</div><div class="photo">Photo 6</div><div class="photo">Photo 7</div><div class="photo">Photo 8</div><div class="photo">Photo 9</div></div>
</body>
</html>
Phase D
Responsive Real Layouts
Media queries, nesting, page shells and dashboards
34Phase D · Step 34
Use media queries when the design needs a specific change
Not every responsive change should be automatic.
A media query applies CSS only when a condition is true. Use it when the layout itself should change at a chosen width.
Smallest useful code
.page {
display:grid;
grid-template-columns:220px 1fr;
}
@media (max-width:700px) {
.page { grid-template-columns:1fr; }
}
What you should see
Parent / layoutChild AChild B
Run the full example below for the exact result. The diagram is only a mental model.
Change this: Change 700px to 900px. Resize and find exactly when the layout collapses.
Full runnable HTML for Step 34 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 34: Use media queries when the design needs a specific change</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.page{display:grid;grid-template-columns:220px 1fr;gap:12px}.box{padding:22px;border:2px solid #0b67b2;background:white}@media(max-width:700px){.page{grid-template-columns:1fr}}
</style>
</head>
<body>
<div class="page"><aside class="box">Sidebar</aside><main class="box">Main content</main></div>
</body>
</html>
35Phase D · Step 35
Put Flexbox inside Grid
Real pages use more than one layout system.
Grid can define the large page structure while Flexbox arranges small controls inside a grid region.
Smallest useful code
.page { display:grid; grid-template-columns:220px 1fr; }
.toolbar { display:flex; justify-content:space-between; gap:12px; }
What you should see
Parent / layoutChild AChild B
Run the full example below for the exact result. The diagram is only a mental model.
Change this: Add a third button. Then make the action group wrap on a very narrow width.
Full runnable HTML for Step 35 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 35: Put Flexbox inside Grid</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.page{display:grid;grid-template-columns:220px 1fr;gap:12px}.side,.main{border:2px solid #0b67b2;background:white;padding:16px}.toolbar{display:flex;justify-content:space-between;align-items:center;gap:12px;flex-wrap:wrap;padding:12px;background:#eef7ff}.actions{display:flex;gap:8px}.actions button{padding:8px 12px} @media(max-width:700px){.page{grid-template-columns:1fr}}
</style>
</head>
<body>
<div class="page"><aside class="side">Sidebar</aside><main class="main"><div class="toolbar"><strong>Dashboard</strong><div class="actions"><button>Save</button><button>Share</button></div></div><p>Main content</p></main></div>
</body>
</html>
36Phase D · Step 36
Put Grid inside Flexbox
A Flexbox region can contain a Grid collection.
For example, a vertical app shell can be a column flex container while the content area contains a responsive card grid.
Smallest useful code
.app { display:flex; flex-direction:column; min-height:100vh; }
.cards { display:grid; grid-template-columns:repeat(auto-fit,minmax(160px,1fr)); }
What you should see
Parent / layoutChild AChild B
Run the full example below for the exact result. The diagram is only a mental model.
Change this: Add enough cards to create several rows.
Full runnable HTML for Step 36 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 36: Put Grid inside Flexbox</title>
<style>
body{margin:0;font-family:Arial,sans-serif}.app{display:flex;flex-direction:column;min-height:100vh}.top{padding:16px;background:#0b67b2;color:white}.content{flex:1;padding:20px;background:#f5f8fb}.cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:12px}.card{padding:22px;border:2px solid #0b67b2;background:white}.foot{padding:14px;text-align:center;background:#ddebf5}
</style>
</head>
<body>
<div class="app"><header class="top">Header</header><main class="content"><div class="cards"><div class="card">Card 1</div><div class="card">Card 2</div><div class="card">Card 3</div><div class="card">Card 4</div><div class="card">Card 5</div><div class="card">Card 6</div></div></main><footer class="foot">Footer</footer></div>
</body>
</html>
37Phase D · Step 37
Build a complete responsive page shell
Now combine header, sidebar, main content and footer.
This is a practical page architecture: Grid for shell, Flexbox for header actions, Grid for cards.
Smallest useful code
.shell {
display:grid;
grid-template-columns:240px minmax(0,1fr);
grid-template-areas:"top top" "side main" "foot foot";
}
@media(max-width:760px){
.shell { grid-template-columns:1fr; grid-template-areas:"top" "side" "main" "foot"; }
}
What you should see
Parent / layoutChild AChild B
Run the full example below for the exact result. The diagram is only a mental model.
Change this: On mobile, try hiding the sidebar instead of stacking it. Which behaviour fits your project?
Full runnable HTML for Step 37 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 37: Build a complete responsive page shell</title>
<style>
body{margin:0;font-family:Arial,sans-serif}.shell{min-height:100vh;display:grid;grid-template-columns:240px minmax(0,1fr);grid-template-areas:"top top" "side main" "foot foot";grid-template-rows:auto 1fr auto}.top{grid-area:top;display:flex;justify-content:space-between;gap:12px;flex-wrap:wrap;padding:16px 22px;background:#0b67b2;color:white}.side{grid-area:side;padding:18px;background:#eaf4fb}.main{grid-area:main;padding:18px;background:#f7fafc}.foot{grid-area:foot;padding:14px;text-align:center;background:#dceaf4}.cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(170px,1fr));gap:12px}.card{padding:20px;border:1px solid #bcd1df;background:white;border-radius:10px}@media(max-width:760px){.shell{grid-template-columns:1fr;grid-template-areas:"top" "side" "main" "foot"}}
</style>
</head>
<body>
<div class="shell"><header class="top"><strong>Site</strong><span>Login</span></header><aside class="side">Sidebar navigation</aside><main class="main"><h1>Content</h1><div class="cards"><div class="card">Card 1</div><div class="card">Card 2</div><div class="card">Card 3</div><div class="card">Card 4</div><div class="card">Card 5</div><div class="card">Card 6</div></div></main><footer class="foot">Footer</footer></div>
</body>
</html>
38Phase D · Step 38
Dashboard project
Dashboards are excellent Grid + Flex practice.
Use Grid for the dashboard shell and summary cards; use Flexbox for the toolbar and small action groups.
Smallest useful code
.dashboard { display:grid; grid-template-columns:220px minmax(0,1fr); gap:16px; }
.toolbar { display:flex; justify-content:space-between; flex-wrap:wrap; }
.stats { display:grid; grid-template-columns:repeat(auto-fit,minmax(160px,1fr)); }
What you should see
Parent / layoutChild AChild B
Run the full example below for the exact result. The diagram is only a mental model.
Change this: Add a fourth stat. Then change the content split from 2fr 1fr to 3fr 2fr.
Full runnable HTML for Step 38 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 38: Dashboard project</title>
<style>
body{margin:0;font-family:Arial,sans-serif;background:#f5f8fb;color:#203040}.dashboard{display:grid;grid-template-columns:220px minmax(0,1fr);gap:16px;min-height:100vh}.sidebar{padding:20px;background:#17324d;color:white}.main{padding:20px}.toolbar{display:flex;justify-content:space-between;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:16px}.actions{display:flex;gap:8px}.stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:12px}.stat,.panel{padding:20px;background:white;border:1px solid #d3e0e9;border-radius:12px}.content{display:grid;grid-template-columns:2fr 1fr;gap:12px;margin-top:12px}@media(max-width:800px){.dashboard{grid-template-columns:1fr}.content{grid-template-columns:1fr}}
</style>
</head>
<body>
<div class="dashboard"><aside class="sidebar"><h2>Menu</h2><p>Overview</p><p>Students</p><p>Lessons</p></aside><main class="main"><div class="toolbar"><h1>Dashboard</h1><div class="actions"><button>Export</button><button>Add</button></div></div><section class="stats"><div class="stat"><strong>120</strong><br>Students</div><div class="stat"><strong>18</strong><br>Lessons</div><div class="stat"><strong>92%</strong><br>Completion</div></section><section class="content"><div class="panel">Main chart / table area</div><div class="panel">Recent activity</div></section></main></div>
</body>
</html>
Phase E
Advanced + Debugging
Overflow, content sizing, fluid design, subgrid and accessibility
39Phase E · Step 39
Debug Flexbox systematically
Most Flexbox bugs come from applying a property to the wrong element or misunderstanding the axis.
Check: Is display:flex on the correct parent? Are the things you want to arrange direct children? What is the current flex-direction? Is there actually free space for justify-content to distribute?
Smallest useful code
/* Debug checklist */
.parent {
outline:3px dashed red;
display:flex;
}
.parent > * { outline:2px solid blue; }
What you should see
Parent / layoutChild AChild B
Run the full example below for the exact result. The diagram is only a mental model.
Change this: Intentionally put display:flex on one child instead of the parent. Diagnose why the siblings do not line up.
Full runnable HTML for Step 39 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 39: Debug Flexbox systematically</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.parent{outline:3px dashed #c43;display:flex;gap:10px;padding:12px}.parent>*{outline:2px solid #1670b5;padding:16px;background:white}
</style>
</head>
<body>
<div class="parent"><div>A</div><div>B</div><div>C</div></div>
</body>
</html>
40Phase E · Step 40
Debug Grid systematically
Grid bugs often come from track sizing, overflowing content or placing an item outside the intended lines.
Temporarily add outlines, inspect the parent’s grid-template-columns, and use minmax(0,1fr) or min-width:0 when long content refuses to shrink.
Smallest useful code
.page {
display:grid;
grid-template-columns:220px minmax(0,1fr);
}
.main { min-width:0; }
What you should see
Parent / layoutChild AChild B
Run the full example below for the exact result. The diagram is only a mental model.
Change this: Replace minmax(0,1fr) with 1fr and remove min-width:0. Test with long content.
Full runnable HTML for Step 40 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 40: Debug Grid systematically</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.page{display:grid;grid-template-columns:220px minmax(0,1fr);gap:12px;outline:3px dashed #c43}.side,.main{outline:2px solid #1670b5;padding:14px;background:white}.main{min-width:0;overflow-wrap:anywhere}
</style>
</head>
<body>
<div class="page"><aside class="side">Sidebar</aside><main class="main">VeryLongUnbrokenContentThatWouldOtherwiseTryToForceTheTrackWiderThanExpected_1234567890</main></div>
</body>
</html>
41Phase E · Step 41
Use content-aware track sizes
Grid tracks can respond to both content and available space.
min-content, max-content, auto, minmax() and fit-content() help when fixed widths are too rigid.
Smallest useful code
.page {
display:grid;
grid-template-columns:max-content minmax(0,1fr);
}
What you should see
Parent / layoutChild AChild B
Run the full example below for the exact result. The diagram is only a mental model.
Change this: Change max-content to 180px, then auto. Compare how the sidebar is sized.
Full runnable HTML for Step 41 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 41: Use content-aware track sizes</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.page{display:grid;grid-template-columns:max-content minmax(0,1fr);gap:12px}.side,.main{padding:18px;border:2px solid #0b67b2;background:white}
</style>
</head>
<body>
<div class="page"><aside class="side">Menu item with natural width</aside><main class="main">The main column takes the remaining space.</main></div>
</body>
</html>
42Phase E · Step 42
Use clamp() for fluid sizing
Layout often works better when typography and spacing also scale fluidly.
clamp(min, preferred, max) keeps a value within safe limits while allowing it to grow with the viewport.
Smallest useful code
h1 {
font-size:clamp(2rem, 6vw, 5rem);
}
.wrapper {
padding:clamp(16px, 4vw, 56px);
}
What you should see
Parent / layoutChild AChild B
Run the full example below for the exact result. The diagram is only a mental model.
Change this: Resize the page slowly and watch the heading, page padding and gap scale without sudden jumps.
Full runnable HTML for Step 42 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 42: Use clamp() for fluid sizing</title>
<style>
body{margin:0;font-family:Arial,sans-serif}.wrapper{padding:clamp(16px,4vw,56px);background:#eaf6ff;min-height:100vh}.wrapper h1{font-size:clamp(2rem,6vw,5rem);margin:0 0 16px}.cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:clamp(10px,2vw,24px)}.card{padding:20px;background:white;border:2px solid #0b67b2}
</style>
</head>
<body>
<main class="wrapper"><h1>Fluid layout</h1><div class="cards"><div class="card">A</div><div class="card">B</div><div class="card">C</div></div></main>
</body>
</html>
43Phase E · Step 43
Understand subgrid
subgrid lets a nested grid reuse the parent’s track definition where supported.
It is useful when child components need their internal rows or columns to line up with siblings. It is an advanced tool, not a requirement for ordinary layouts.
Smallest useful code
.cards {
display:grid;
grid-template-columns:repeat(3,1fr);
}
.card {
display:grid;
grid-row:span 3;
grid-template-rows:subgrid;
}
What you should see
Parent / layoutChild AChild B
Run the full example below for the exact result. The diagram is only a mental model.
Change this: First understand the non-subgrid fallback. Then inspect whether your browser applies the @supports block.
Full runnable HTML for Step 43 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 43: Understand subgrid</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.cards{display:grid;grid-template-columns:repeat(3,1fr);gap:12px}.card{display:grid;grid-template-rows:auto 1fr auto;gap:8px;padding:16px;border:2px solid #0b67b2;background:white}@supports(grid-template-rows:subgrid){.cards{grid-auto-rows:auto}.card{grid-row:span 3;grid-template-rows:subgrid}}@media(max-width:700px){.cards{grid-template-columns:1fr}}
</style>
</head>
<body>
<div class="cards"><article class="card"><h2>Short title</h2><p>Short text.</p><button>Open</button></article><article class="card"><h2>A much longer title that wraps</h2><p>More text in this card to create a different natural height.</p><button>Open</button></article><article class="card"><h2>Third</h2><p>Text.</p><button>Open</button></article></div>
</body>
</html>
44Phase E · Step 44
Accessibility: visual layout must not destroy meaning
Good layout keeps the source order logical.
Flexbox and Grid can move things visually, but users may navigate by keyboard, screen reader or source order. Build semantic HTML first, then style it.
Smallest useful code
<header>...</header>
<nav>...</nav>
<main>...</main>
<aside>...</aside>
<footer>...</footer>
What you should see
Parent / layoutChild AChild B
Run the full example below for the exact result. The diagram is only a mental model.
Change this: Tab through any interactive elements you add. Make sure the focus order still makes sense.
Full runnable HTML for Step 44 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 44: Accessibility: visual layout must not destroy meaning</title>
<style>
body{margin:0;font-family:Arial,sans-serif}.page{display:grid;grid-template-columns:1fr 260px;grid-template-areas:"head head" "main side" "foot foot";gap:12px;padding:16px}.box{padding:18px;border:2px solid #0b67b2;background:white}header{grid-area:head}main{grid-area:main}aside{grid-area:side}footer{grid-area:foot}@media(max-width:700px){.page{grid-template-columns:1fr;grid-template-areas:"head" "main" "side" "foot"}}
</style>
</head>
<body>
<div class="page"><header class="box">Header and navigation</header><main class="box"><h1>Main content first</h1><p>The important reading content remains logically before the sidebar.</p></main><aside class="box">Supporting information</aside><footer class="box">Footer</footer></div>
</body>
</html>
Phase F
Infinity Project
Design from a layout plan instead of memorising properties
45Phase F · Step 45
Capstone: build from a layout plan
At infinity, you choose containers and layout systems deliberately.
Plan first: page shell = Grid; toolbar = Flexbox; summary cards = Grid; action group = Flexbox; content split = Grid; mobile behaviour = media query.
Smallest useful code
/* 1. Shell */
.app { display:grid; grid-template-columns:230px minmax(0,1fr); }
/* 2. Toolbar */
.toolbar { display:flex; justify-content:space-between; flex-wrap:wrap; }
/* 3. Cards */
.cards { display:grid; grid-template-columns:repeat(auto-fit,minmax(170px,1fr)); }
What you should see
Parent / layoutChild AChild B
Run the full example below for the exact result. The diagram is only a mental model.
Change this: Delete the CSS and rebuild the capstone from the plan comments only. That is the final exercise.
Full runnable HTML for Step 45 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 45: Capstone: build from a layout plan</title>
<style>
body{margin:0;font-family:Arial,sans-serif;background:#f4f7fa;color:#1e3040}.app{display:grid;grid-template-columns:230px minmax(0,1fr);min-height:100vh}.sidebar{padding:22px;background:#17324d;color:white}.main{padding:22px}.toolbar{display:flex;justify-content:space-between;align-items:center;gap:12px;flex-wrap:wrap}.actions{display:flex;gap:8px;flex-wrap:wrap}.cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(170px,1fr));gap:14px;margin:18px 0}.card,.panel{background:white;border:1px solid #d2dfe8;border-radius:12px;padding:18px}.content{display:grid;grid-template-columns:minmax(0,2fr) minmax(240px,1fr);gap:14px}.list{display:grid;gap:10px}.list>div{padding:12px;background:#eef6fb;border-radius:8px}@media(max-width:820px){.app{grid-template-columns:1fr}.sidebar{display:none}.content{grid-template-columns:1fr}}
</style>
</head>
<body>
<div class="app"><aside class="sidebar"><h2>Learn</h2><p>Dashboard</p><p>Lessons</p><p>Projects</p><p>Profile</p></aside><main class="main"><div class="toolbar"><div><small>Welcome back</small><h1>Learning Dashboard</h1></div><div class="actions"><button>Search</button><button>Share</button><button>New Project</button></div></div><section class="cards"><div class="card"><strong>12</strong><br>Lessons</div><div class="card"><strong>8</strong><br>Projects</div><div class="card"><strong>72%</strong><br>Progress</div><div class="card"><strong>4</strong><br>Challenges</div></section><section class="content"><article class="panel"><h2>Current lesson</h2><p>Build a responsive page from containers. Decide whether each container needs one-dimensional or two-dimensional control.</p><div class="list"><div>1. Identify the parent</div><div>2. Identify its direct children</div><div>3. Choose Flex or Grid</div><div>4. Add responsiveness</div></div></article><aside class="panel"><h2>Next</h2><p>Rebuild this layout without looking at the CSS.</p></aside></section></main></div>
</body>
</html>
Fast reference
Which element receives which property?
Flex parent
display:flex, flex-direction, flex-wrap, justify-content, align-items, align-content, gapFlex child
flex, flex-grow, flex-shrink, flex-basis, align-self, orderGrid parent
display:grid, grid-template-columns, grid-template-rows, grid-template-areas, grid-auto-flow, place-items, gapGrid child
grid-column, grid-row, grid-area, justify-self, align-self
∞Infinity
You can now design a layout instead of copying one
The useful meaning of “∞” is not knowing every CSS property. It is being able to look at a page, divide it into containers, choose the right layout system for each container, make it responsive, and debug it when content or screen size changes.
1. Draw containers
Header, sidebar, toolbar, cards, article, footer.2. Ask one axis or two?
One main row/column → Flexbox. Explicit rows + columns → Grid.3. Prefer fluid rules
Use fr, minmax(), wrapping and useful minimums before hard-coded widths everywhere.4. Test ugly cases
Very long text, many items, one item, narrow phone, wide screen, zoom, keyboard navigation.Final challenge: rebuild Step 45 without looking at its CSS. Explain aloud why each parent uses Flexbox or Grid.
A
Smallest useful code
<div>My first box</div>What you should see
Run the full example below for the exact result. The diagram is only a mental model.
Full runnable HTML for Step 1 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 1: Make your first box with <div></title>
<style>
body { font-family: Arial, sans-serif; padding: 24px; }
div { border: 2px solid #0b67b2; padding: 20px; }
</style>
</head>
<body>
<div>My first box</div>
</body>
</html>Phase A · Step 2
Give boxes classes
A class gives a reusable name to one or more elements.
Smallest useful code
<div class="box">A</div>
<div class="box">B</div>What you should see
Run the full example below for the exact result. The diagram is only a mental model.
Full runnable HTML for Step 2 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 2: Give boxes classes</title>
<style>
body {
margin: 0;
padding: 24px;
font-family: Arial, sans-serif;
background: #f5f8fb;
color: #203040;
}
.box {
padding: 18px;
border: 2px solid #0b67b2;
border-radius: 10px;
background: white;
text-align: center;
font-weight: bold;
}
</style>
</head>
<body>
<div class="box">A</div>
<br>
<div class="box">B</div>
</body>
</html>Phase A · Step 3
Understand width, padding, border and margin
Every element is a rectangular box.
Smallest useful code
.box {
width: 220px;
padding: 20px;
border: 4px solid #0b67b2;
margin: 20px;
}What you should see
Run the full example below for the exact result. The diagram is only a mental model.
Full runnable HTML for Step 3 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 3: Understand width, padding, border and margin</title>
<style>
body { font-family: Arial, sans-serif; }
.box { width:220px; padding:20px; border:4px solid #0b67b2; margin:20px; background:#fff; }
</style>
</head>
<body>
<div class="box">Content → padding → border → margin</div>
</body>
</html>Phase A · Step 4
Parent and children
Flexbox and Grid are usually applied to a parent.
Smallest useful code
<div class="parent">
<div class="child">A</div>
<div class="child">B</div>
<div class="child">C</div>
</div>What you should see
Run the full example below for the exact result. The diagram is only a mental model.
Full runnable HTML for Step 4 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 4: Parent and children</title>
<style>
body { font-family:Arial,sans-serif; padding:24px; }
.parent { border:3px dashed #7997ad; padding:12px; }
.child { border:2px solid #0b67b2; padding:14px; margin:8px 0; }
</style>
</head>
<body>
<div class="parent">
<div class="child">A</div>
<div class="child">B</div>
<div class="child">C</div>
</div>
</body>
</html>Phase A · Step 5
See normal document flow
Block elements naturally stack vertically.
Smallest useful code
.parent { border: 3px dashed #7997ad; }
.child { padding: 16px; border: 2px solid #0b67b2; }What you should see
Run the full example below for the exact result. The diagram is only a mental model.
Full runnable HTML for Step 5 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 5: See normal document flow</title>
<style>
body { font-family:Arial,sans-serif; padding:24px; }
.parent { border:3px dashed #7997ad; padding:12px; }
.child { padding:16px; border:2px solid #0b67b2; background:white; }
</style>
</head>
<body>
<div class="parent">
<div class="child">One</div>
<div class="child">Two</div>
<div class="child">Three</div>
</div>
</body>
</html>Phase B
Flexbox Foundations
One-dimensional layout from first line to mini-project
Phase B · Step 6
Your first Flexbox
One line changes the children from normal block flow into flex items.
Smallest useful code
.parent {
display: flex;
}What you should see
Run the full example below for the exact result. The diagram is only a mental model.
Full runnable HTML for Step 6 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 6: Your first Flexbox</title>
<style>
body { font-family:Arial,sans-serif; padding:24px; }
.parent { display:flex; border:3px dashed #7997ad; padding:12px; }
.child { padding:16px; border:2px solid #0b67b2; background:white; }
</style>
</head>
<body>
<div class="parent">
<div class="child">One</div>
<div class="child">Two</div>
<div class="child">Three</div>
</div>
</body>
</html>Phase B · Step 7
Main axis and cross axis
Flexbox always has a main axis and a cross axis.
Smallest useful code
.parent {
display: flex;
/* main axis → */
/* cross axis ↓ */
}What you should see
Run the full example below for the exact result. The diagram is only a mental model.
Full runnable HTML for Step 7 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 7: Main axis and cross axis</title>
<style>
body {font-family:Arial,sans-serif;padding:24px}.parent{display:flex;min-height:180px;border:3px dashed #7997ad;padding:12px}.child{padding:16px;border:2px solid #0b67b2;background:white}
</style>
</head>
<body>
<div class="parent">
<div class="child">A</div>
<div class="child">B</div>
<div class="child">C</div>
</div>
</body>
</html>Phase B · Step 8
Change flex direction
flex-direction chooses the main axis.
Smallest useful code
.parent {
display: flex;
flex-direction: column;
}What you should see
Run the full example below for the exact result. The diagram is only a mental model.
Full runnable HTML for Step 8 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 8: Change flex direction</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.parent{display:flex;flex-direction:column;gap:10px;border:3px dashed #7997ad;padding:12px}.child{padding:16px;border:2px solid #0b67b2;background:white}
</style>
</head>
<body>
<div class="parent"><div class="child">A</div><div class="child">B</div><div class="child">C</div></div>
</body>
</html>Phase B · Step 9
Add clean spacing with gap
gap creates space between flex items without outside-edge margin problems.
Smallest useful code
.parent {
display: flex;
gap: 16px;
}What you should see
Run the full example below for the exact result. The diagram is only a mental model.
Full runnable HTML for Step 9 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 9: Add clean spacing with gap</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.parent{display:flex;gap:16px;border:3px dashed #7997ad;padding:12px}.child{padding:16px;border:2px solid #0b67b2;background:white}
</style>
</head>
<body>
<div class="parent"><div class="child">A</div><div class="child">B</div><div class="child">C</div></div>
</body>
</html>Phase B · Step 10
Move items along the main axis
justify-content distributes free space on the main axis.
Smallest useful code
.parent {
display: flex;
justify-content: space-between;
}What you should see
Run the full example below for the exact result. The diagram is only a mental model.
Full runnable HTML for Step 10 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 10: Move items along the main axis</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.parent{display:flex;justify-content:space-between;gap:10px;border:3px dashed #7997ad;padding:12px}.child{padding:16px;border:2px solid #0b67b2;background:white}
</style>
</head>
<body>
<div class="parent"><div class="child">A</div><div class="child">B</div><div class="child">C</div></div>
</body>
</html>Phase B · Step 11
Move items along the cross axis
align-items aligns flex items on the cross axis.
Smallest useful code
.parent {
display: flex;
min-height: 220px;
align-items: center;
}What you should see
Run the full example below for the exact result. The diagram is only a mental model.
Full runnable HTML for Step 11 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 11: Move items along the cross axis</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.parent{display:flex;min-height:220px;align-items:center;gap:10px;border:3px dashed #7997ad;padding:12px}.child{padding:16px;border:2px solid #0b67b2;background:white}
</style>
</head>
<body>
<div class="parent"><div class="child">Short</div><div class="child">Medium box</div><div class="child">Tall?</div></div>
</body>
</html>Phase B · Step 12
Center something both ways
Combine justify-content and align-items.
Smallest useful code
.parent {
display: flex;
justify-content: center;
align-items: center;
min-height: 300px;
}What you should see
Run the full example below for the exact result. The diagram is only a mental model.
Full runnable HTML for Step 12 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 12: Center something both ways</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.parent{display:flex;justify-content:center;align-items:center;min-height:300px;border:3px dashed #7997ad}.child{padding:24px;border:2px solid #0b67b2;background:white;border-radius:10px}
</style>
</head>
<body>
<div class="parent"><div class="child">Perfectly centered</div></div>
</body>
</html>Phase B · Step 13
Allow items to wrap
flex-wrap lets items move to another line when space runs out.
Smallest useful code
.parent {
display: flex;
flex-wrap: wrap;
gap: 12px;
}
.child { width: 180px; }What you should see
Run the full example below for the exact result. The diagram is only a mental model.
Full runnable HTML for Step 13 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 13: Allow items to wrap</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.parent{display:flex;flex-wrap:wrap;gap:12px;border:3px dashed #7997ad;padding:12px}.child{width:180px;padding:16px;border:2px solid #0b67b2;background:white}
</style>
</head>
<body>
<div class="parent"><div class="child">Item 1</div><div class="child">Item 2</div><div class="child">Item 3</div><div class="child">Item 4</div><div class="child">Item 5</div><div class="child">Item 6</div></div>
</body>
</html>Phase B · Step 14
Choose a starting size with flex-basis
flex-basis is the preferred main-axis starting size.
Smallest useful code
.child {
flex-basis: 180px;
}What you should see
Run the full example below for the exact result. The diagram is only a mental model.
Full runnable HTML for Step 14 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 14: Choose a starting size with flex-basis</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.parent{display:flex;flex-wrap:wrap;gap:12px}.child{flex-basis:180px;padding:16px;border:2px solid #0b67b2;background:white}
</style>
</head>
<body>
<div class="parent"><div class="child">Card 1</div><div class="child">Card 2</div><div class="child">Card 3</div><div class="child">Card 4</div><div class="child">Card 5</div></div>
</body>
</html>Phase B · Step 15
Let items grow
flex-grow decides how leftover space is shared.
Smallest useful code
.a { flex-grow: 1; }
.b { flex-grow: 2; }
.c { flex-grow: 1; }What you should see
Run the full example below for the exact result. The diagram is only a mental model.
Full runnable HTML for Step 15 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 15: Let items grow</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.parent{display:flex;gap:10px}.child{padding:16px;border:2px solid #0b67b2;background:white}.a,.c{flex-grow:1}.b{flex-grow:2}
</style>
</head>
<body>
<div class="parent"><div class="child a">1 share</div><div class="child b">2 shares</div><div class="child c">1 share</div></div>
</body>
</html>Phase B · Step 16
Control shrinking
flex-shrink decides how items give up space when there is not enough room.
Smallest useful code
.fixed {
width: 240px;
flex-shrink: 0;
}What you should see
Run the full example below for the exact result. The diagram is only a mental model.
Full runnable HTML for Step 16 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 16: Control shrinking</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.parent{display:flex;gap:10px;width:420px;max-width:100%;border:3px dashed #7997ad}.child{width:240px;padding:16px;border:2px solid #0b67b2;background:white}.fixed{flex-shrink:0}
</style>
</head>
<body>
<div class="parent"><div class="child fixed">I do not shrink</div><div class="child">I can shrink</div></div>
</body>
</html>Phase B · Step 17
Use the flex shorthand
flex combines grow, shrink and basis.
Smallest useful code
.child {
flex: 1 1 200px;
}What you should see
Run the full example below for the exact result. The diagram is only a mental model.
Full runnable HTML for Step 17 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 17: Use the flex shorthand</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.parent{display:flex;flex-wrap:wrap;gap:12px}.child{flex:1 1 200px;padding:16px;border:2px solid #0b67b2;background:white}
</style>
</head>
<body>
<div class="parent"><div class="child">Flexible 1</div><div class="child">Flexible 2</div><div class="child">Flexible 3</div><div class="child">Flexible 4</div></div>
</body>
</html>Phase B · Step 18
Override one item with align-self
align-self changes cross-axis alignment for one flex item.
Smallest useful code
.parent { align-items: flex-start; }
.special { align-self: flex-end; }What you should see
Run the full example below for the exact result. The diagram is only a mental model.
Full runnable HTML for Step 18 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 18: Override one item with align-self</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.parent{display:flex;align-items:flex-start;min-height:220px;gap:10px;border:3px dashed #7997ad}.child{padding:16px;border:2px solid #0b67b2;background:white}.special{align-self:flex-end}
</style>
</head>
<body>
<div class="parent"><div class="child">A</div><div class="child special">Special</div><div class="child">C</div></div>
</body>
</html>Phase B · Step 19
Visual order and source order
order can visually rearrange flex items, but it does not rewrite the document’s logical order.
Smallest useful code
.first-visually { order: -1; }What you should see
Run the full example below for the exact result. The diagram is only a mental model.
Full runnable HTML for Step 19 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 19: Visual order and source order</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.parent{display:flex;gap:10px}.child{padding:16px;border:2px solid #0b67b2;background:white}.first-visually{order:-1}
</style>
</head>
<body>
<div class="parent"><div class="child">HTML first</div><div class="child">HTML second</div><div class="child first-visually">HTML third, visual first</div></div>
</body>
</html>Phase B · Step 20
Flexbox mini-project: navigation bar
A navbar is a natural one-dimensional layout.
Smallest useful code
.nav {
display:flex;
justify-content:space-between;
align-items:center;
gap:16px;
flex-wrap:wrap;
}
.links { display:flex; gap:12px; }What you should see
Run the full example below for the exact result. The diagram is only a mental model.
Full runnable HTML for Step 20 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 20: Flexbox mini-project: navigation bar</title>
<style>
body{margin:0;font-family:Arial,sans-serif}.nav{display:flex;justify-content:space-between;align-items:center;gap:16px;flex-wrap:wrap;padding:16px 24px;background:#0b67b2;color:white}.brand{font-weight:bold;font-size:1.25rem}.links{display:flex;gap:12px;flex-wrap:wrap}.links a{color:white;text-decoration:none;padding:8px 10px;background:rgba(255,255,255,.12);border-radius:8px}
</style>
</head>
<body>
<nav class="nav"><div class="brand">Learn With Champak</div><div class="links"><a href="#">Home</a><a href="#">Lessons</a><a href="#">Practice</a></div></nav>
</body>
</html>Phase C
Grid Foundations
Rows, columns, responsive tracks and named areas
Phase C · Step 21
Your first CSS Grid
display:grid turns direct children into grid items.
Smallest useful code
.parent {
display: grid;
grid-template-columns: 1fr 1fr;
}What you should see
Run the full example below for the exact result. The diagram is only a mental model.
Full runnable HTML for Step 21 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 21: Your first CSS Grid</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.parent{display:grid;grid-template-columns:1fr 1fr;gap:10px}.child{padding:18px;border:2px solid #0b67b2;background:white}
</style>
</head>
<body>
<div class="parent"><div class="child">A</div><div class="child">B</div><div class="child">C</div><div class="child">D</div></div>
</body>
</html>Phase C · Step 22
Make columns with fixed units
grid-template-columns defines the column tracks.
Smallest useful code
.grid {
display:grid;
grid-template-columns: 150px 250px;
}What you should see
Run the full example below for the exact result. The diagram is only a mental model.
Full runnable HTML for Step 22 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 22: Make columns with fixed units</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.grid{display:grid;grid-template-columns:150px 250px;gap:10px;max-width:100%}.item{padding:18px;border:2px solid #0b67b2;background:white}
</style>
</head>
<body>
<div class="grid"><div class="item">150px column</div><div class="item">250px column</div></div>
</body>
</html>Phase C · Step 23
Meet the fr unit
fr means a fraction of the available grid space.
Smallest useful code
.grid {
display:grid;
grid-template-columns: 1fr 2fr;
gap:12px;
}What you should see
Run the full example below for the exact result. The diagram is only a mental model.
Full runnable HTML for Step 23 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 23: Meet the fr unit</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.grid{display:grid;grid-template-columns:1fr 2fr;gap:12px}.item{padding:18px;border:2px solid #0b67b2;background:white}
</style>
</head>
<body>
<div class="grid"><div class="item">1fr</div><div class="item">2fr</div></div>
</body>
</html>Phase C · Step 24
Stop repeating yourself with repeat()
repeat() writes repeated tracks more clearly.
Smallest useful code
.grid {
display:grid;
grid-template-columns: repeat(4, 1fr);
}What you should see
Run the full example below for the exact result. The diagram is only a mental model.
Full runnable HTML for Step 24 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 24: Stop repeating yourself with repeat()</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.grid{display:grid;grid-template-columns:repeat(4,1fr);gap:10px}.item{padding:18px;border:2px solid #0b67b2;background:white}
</style>
</head>
<body>
<div class="grid"><div class="item">1</div><div class="item">2</div><div class="item">3</div><div class="item">4</div><div class="item">5</div><div class="item">6</div><div class="item">7</div><div class="item">8</div></div>
</body>
</html>Phase C · Step 25
Rows and gap
Grid has both column tracks and row tracks.
Smallest useful code
.grid {
display:grid;
grid-template-columns: repeat(3,1fr);
grid-template-rows: 80px 140px;
gap:12px;
}What you should see
Run the full example below for the exact result. The diagram is only a mental model.
Full runnable HTML for Step 25 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 25: Rows and gap</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.grid{display:grid;grid-template-columns:repeat(3,1fr);grid-template-rows:80px 140px;gap:12px}.item{padding:18px;border:2px solid #0b67b2;background:white}
</style>
</head>
<body>
<div class="grid"><div class="item">1</div><div class="item">2</div><div class="item">3</div><div class="item">4</div><div class="item">5</div><div class="item">6</div></div>
</body>
</html>Phase C · Step 26
Align content inside grid cells
place-items is shorthand for align-items and justify-items.
Smallest useful code
.grid {
display:grid;
grid-template-columns:repeat(3,1fr);
grid-auto-rows:120px;
place-items:center;
}What you should see
Run the full example below for the exact result. The diagram is only a mental model.
Full runnable HTML for Step 26 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 26: Align content inside grid cells</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.grid{display:grid;grid-template-columns:repeat(3,1fr);grid-auto-rows:120px;place-items:center;gap:10px;border:3px dashed #7997ad}.item{padding:18px;border:2px solid #0b67b2;background:white}
</style>
</head>
<body>
<div class="grid"><div class="item">A</div><div class="item">B</div><div class="item">C</div></div>
</body>
</html>Phase C · Step 27
Let Grid auto-place items
Grid automatically fills cells in source order unless you tell an item to go somewhere special.
Smallest useful code
.grid {
display:grid;
grid-template-columns:repeat(3,1fr);
gap:12px;
}What you should see
Run the full example below for the exact result. The diagram is only a mental model.
Full runnable HTML for Step 27 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 27: Let Grid auto-place items</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.grid{display:grid;grid-template-columns:repeat(3,1fr);gap:12px}.item{padding:18px;border:2px solid #0b67b2;background:white}
</style>
</head>
<body>
<div class="grid"><div class="item">Card 1</div><div class="item">Card 2</div><div class="item">Card 3</div><div class="item">Card 4</div><div class="item">Card 5</div><div class="item">Card 6</div><div class="item">Card 7</div></div>
</body>
</html>Phase C · Step 28
Give tracks limits with minmax()
minmax(min,max) lets a track stay within useful limits.
Smallest useful code
.grid {
display:grid;
grid-template-columns:repeat(3, minmax(140px, 1fr));
}What you should see
Run the full example below for the exact result. The diagram is only a mental model.
Full runnable HTML for Step 28 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 28: Give tracks limits with minmax()</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.grid{display:grid;grid-template-columns:repeat(3,minmax(140px,1fr));gap:12px}.item{padding:18px;border:2px solid #0b67b2;background:white}
</style>
</head>
<body>
<div class="grid"><div class="item">Card 1</div><div class="item">Card 2</div><div class="item">Card 3</div><div class="item">Card 4</div><div class="item">Card 5</div><div class="item">Card 6</div></div>
</body>
</html>Phase C · Step 29
Responsive cards with auto-fit
auto-fit lets the browser choose how many tracks fit.
Smallest useful code
.grid {
display:grid;
grid-template-columns:repeat(auto-fit, minmax(180px, 1fr));
gap:16px;
}What you should see
Run the full example below for the exact result. The diagram is only a mental model.
Full runnable HTML for Step 29 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 29: Responsive cards with auto-fit</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:16px}.item{padding:24px;border:2px solid #0b67b2;background:white}
</style>
</head>
<body>
<div class="grid"><div class="item">Responsive 1</div><div class="item">Responsive 2</div><div class="item">Responsive 3</div><div class="item">Responsive 4</div><div class="item">Responsive 5</div><div class="item">Responsive 6</div><div class="item">Responsive 7</div><div class="item">Responsive 8</div></div>
</body>
</html>Phase C · Step 30
Make an item span columns
A grid item can occupy more than one track.
Smallest useful code
.wide {
grid-column: span 2;
}What you should see
Run the full example below for the exact result. The diagram is only a mental model.
Full runnable HTML for Step 30 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 30: Make an item span columns</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.grid{display:grid;grid-template-columns:repeat(4,1fr);gap:10px}.item{padding:18px;border:2px solid #0b67b2;background:white}.wide{grid-column:span 2}
</style>
</head>
<body>
<div class="grid"><div class="item wide">I span 2 columns</div><div class="item">B</div><div class="item">C</div><div class="item">D</div><div class="item">E</div></div>
</body>
</html>Phase C · Step 31
Place items using grid lines
Grid tracks are separated by numbered lines.
Smallest useful code
.header {
grid-column: 1 / -1;
}What you should see
Run the full example below for the exact result. The diagram is only a mental model.
Full runnable HTML for Step 31 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 31: Place items using grid lines</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.grid{display:grid;grid-template-columns:repeat(3,1fr);gap:10px}.item{padding:18px;border:2px solid #0b67b2;background:white}.header{grid-column:1 / -1;background:#e8f5ff}
</style>
</head>
<body>
<div class="grid"><div class="item header">Full-width header</div><div class="item">A</div><div class="item">B</div><div class="item">C</div></div>
</body>
</html>Phase C · Step 32
Name page regions with grid-template-areas
Named areas make page-shell CSS readable.
Smallest useful code
.page {
display:grid;
grid-template-columns:220px 1fr;
grid-template-areas:
"header header"
"side main"
"footer footer";
}
header { grid-area:header; }What you should see
Run the full example below for the exact result. The diagram is only a mental model.
Full runnable HTML for Step 32 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 32: Name page regions with grid-template-areas</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.page{display:grid;grid-template-columns:220px 1fr;grid-template-areas:"header header" "side main" "footer footer";gap:10px}.region{padding:22px;border:2px solid #0b67b2;background:white}.head{grid-area:header}.side{grid-area:side}.main{grid-area:main}.foot{grid-area:footer}
</style>
</head>
<body>
<div class="page"><header class="region head">Header</header><aside class="region side">Sidebar</aside><main class="region main">Main</main><footer class="region foot">Footer</footer></div>
</body>
</html>Phase C · Step 33
Grid mini-project: responsive gallery
A gallery is a natural repeated two-dimensional layout.
Smallest useful code
.gallery {
display:grid;
grid-template-columns:repeat(auto-fit,minmax(160px,1fr));
gap:14px;
}What you should see
Run the full example below for the exact result. The diagram is only a mental model.
Full runnable HTML for Step 33 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 33: Grid mini-project: responsive gallery</title>
<style>
body{font-family:Arial,sans-serif;padding:24px;background:#f5f8fb}.gallery{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:14px}.photo{aspect-ratio:4/3;display:grid;place-items:center;border-radius:12px;background:linear-gradient(135deg,#dff1ff,#fff);border:2px solid #0b67b2;font-weight:bold}
</style>
</head>
<body>
<div class="gallery"><div class="photo">Photo 1</div><div class="photo">Photo 2</div><div class="photo">Photo 3</div><div class="photo">Photo 4</div><div class="photo">Photo 5</div><div class="photo">Photo 6</div><div class="photo">Photo 7</div><div class="photo">Photo 8</div><div class="photo">Photo 9</div></div>
</body>
</html>Phase D
Responsive Real Layouts
Media queries, nesting, page shells and dashboards
Phase D · Step 34
Use media queries when the design needs a specific change
Not every responsive change should be automatic.
Smallest useful code
.page {
display:grid;
grid-template-columns:220px 1fr;
}
@media (max-width:700px) {
.page { grid-template-columns:1fr; }
}What you should see
Run the full example below for the exact result. The diagram is only a mental model.
Full runnable HTML for Step 34 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 34: Use media queries when the design needs a specific change</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.page{display:grid;grid-template-columns:220px 1fr;gap:12px}.box{padding:22px;border:2px solid #0b67b2;background:white}@media(max-width:700px){.page{grid-template-columns:1fr}}
</style>
</head>
<body>
<div class="page"><aside class="box">Sidebar</aside><main class="box">Main content</main></div>
</body>
</html>Phase D · Step 35
Put Flexbox inside Grid
Real pages use more than one layout system.
Smallest useful code
.page { display:grid; grid-template-columns:220px 1fr; }
.toolbar { display:flex; justify-content:space-between; gap:12px; }What you should see
Run the full example below for the exact result. The diagram is only a mental model.
Full runnable HTML for Step 35 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 35: Put Flexbox inside Grid</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.page{display:grid;grid-template-columns:220px 1fr;gap:12px}.side,.main{border:2px solid #0b67b2;background:white;padding:16px}.toolbar{display:flex;justify-content:space-between;align-items:center;gap:12px;flex-wrap:wrap;padding:12px;background:#eef7ff}.actions{display:flex;gap:8px}.actions button{padding:8px 12px} @media(max-width:700px){.page{grid-template-columns:1fr}}
</style>
</head>
<body>
<div class="page"><aside class="side">Sidebar</aside><main class="main"><div class="toolbar"><strong>Dashboard</strong><div class="actions"><button>Save</button><button>Share</button></div></div><p>Main content</p></main></div>
</body>
</html>Phase D · Step 36
Put Grid inside Flexbox
A Flexbox region can contain a Grid collection.
Smallest useful code
.app { display:flex; flex-direction:column; min-height:100vh; }
.cards { display:grid; grid-template-columns:repeat(auto-fit,minmax(160px,1fr)); }What you should see
Run the full example below for the exact result. The diagram is only a mental model.
Full runnable HTML for Step 36 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 36: Put Grid inside Flexbox</title>
<style>
body{margin:0;font-family:Arial,sans-serif}.app{display:flex;flex-direction:column;min-height:100vh}.top{padding:16px;background:#0b67b2;color:white}.content{flex:1;padding:20px;background:#f5f8fb}.cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:12px}.card{padding:22px;border:2px solid #0b67b2;background:white}.foot{padding:14px;text-align:center;background:#ddebf5}
</style>
</head>
<body>
<div class="app"><header class="top">Header</header><main class="content"><div class="cards"><div class="card">Card 1</div><div class="card">Card 2</div><div class="card">Card 3</div><div class="card">Card 4</div><div class="card">Card 5</div><div class="card">Card 6</div></div></main><footer class="foot">Footer</footer></div>
</body>
</html>Phase D · Step 37
Build a complete responsive page shell
Now combine header, sidebar, main content and footer.
Smallest useful code
.shell {
display:grid;
grid-template-columns:240px minmax(0,1fr);
grid-template-areas:"top top" "side main" "foot foot";
}
@media(max-width:760px){
.shell { grid-template-columns:1fr; grid-template-areas:"top" "side" "main" "foot"; }
}What you should see
Run the full example below for the exact result. The diagram is only a mental model.
Full runnable HTML for Step 37 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 37: Build a complete responsive page shell</title>
<style>
body{margin:0;font-family:Arial,sans-serif}.shell{min-height:100vh;display:grid;grid-template-columns:240px minmax(0,1fr);grid-template-areas:"top top" "side main" "foot foot";grid-template-rows:auto 1fr auto}.top{grid-area:top;display:flex;justify-content:space-between;gap:12px;flex-wrap:wrap;padding:16px 22px;background:#0b67b2;color:white}.side{grid-area:side;padding:18px;background:#eaf4fb}.main{grid-area:main;padding:18px;background:#f7fafc}.foot{grid-area:foot;padding:14px;text-align:center;background:#dceaf4}.cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(170px,1fr));gap:12px}.card{padding:20px;border:1px solid #bcd1df;background:white;border-radius:10px}@media(max-width:760px){.shell{grid-template-columns:1fr;grid-template-areas:"top" "side" "main" "foot"}}
</style>
</head>
<body>
<div class="shell"><header class="top"><strong>Site</strong><span>Login</span></header><aside class="side">Sidebar navigation</aside><main class="main"><h1>Content</h1><div class="cards"><div class="card">Card 1</div><div class="card">Card 2</div><div class="card">Card 3</div><div class="card">Card 4</div><div class="card">Card 5</div><div class="card">Card 6</div></div></main><footer class="foot">Footer</footer></div>
</body>
</html>Phase D · Step 38
Dashboard project
Dashboards are excellent Grid + Flex practice.
Smallest useful code
.dashboard { display:grid; grid-template-columns:220px minmax(0,1fr); gap:16px; }
.toolbar { display:flex; justify-content:space-between; flex-wrap:wrap; }
.stats { display:grid; grid-template-columns:repeat(auto-fit,minmax(160px,1fr)); }What you should see
Run the full example below for the exact result. The diagram is only a mental model.
Full runnable HTML for Step 38 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 38: Dashboard project</title>
<style>
body{margin:0;font-family:Arial,sans-serif;background:#f5f8fb;color:#203040}.dashboard{display:grid;grid-template-columns:220px minmax(0,1fr);gap:16px;min-height:100vh}.sidebar{padding:20px;background:#17324d;color:white}.main{padding:20px}.toolbar{display:flex;justify-content:space-between;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:16px}.actions{display:flex;gap:8px}.stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:12px}.stat,.panel{padding:20px;background:white;border:1px solid #d3e0e9;border-radius:12px}.content{display:grid;grid-template-columns:2fr 1fr;gap:12px;margin-top:12px}@media(max-width:800px){.dashboard{grid-template-columns:1fr}.content{grid-template-columns:1fr}}
</style>
</head>
<body>
<div class="dashboard"><aside class="sidebar"><h2>Menu</h2><p>Overview</p><p>Students</p><p>Lessons</p></aside><main class="main"><div class="toolbar"><h1>Dashboard</h1><div class="actions"><button>Export</button><button>Add</button></div></div><section class="stats"><div class="stat"><strong>120</strong><br>Students</div><div class="stat"><strong>18</strong><br>Lessons</div><div class="stat"><strong>92%</strong><br>Completion</div></section><section class="content"><div class="panel">Main chart / table area</div><div class="panel">Recent activity</div></section></main></div>
</body>
</html>Phase E
Advanced + Debugging
Overflow, content sizing, fluid design, subgrid and accessibility
Phase E · Step 39
Debug Flexbox systematically
Most Flexbox bugs come from applying a property to the wrong element or misunderstanding the axis.
Smallest useful code
/* Debug checklist */
.parent {
outline:3px dashed red;
display:flex;
}
.parent > * { outline:2px solid blue; }What you should see
Run the full example below for the exact result. The diagram is only a mental model.
Full runnable HTML for Step 39 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 39: Debug Flexbox systematically</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.parent{outline:3px dashed #c43;display:flex;gap:10px;padding:12px}.parent>*{outline:2px solid #1670b5;padding:16px;background:white}
</style>
</head>
<body>
<div class="parent"><div>A</div><div>B</div><div>C</div></div>
</body>
</html>Phase E · Step 40
Debug Grid systematically
Grid bugs often come from track sizing, overflowing content or placing an item outside the intended lines.
Smallest useful code
.page {
display:grid;
grid-template-columns:220px minmax(0,1fr);
}
.main { min-width:0; }What you should see
Run the full example below for the exact result. The diagram is only a mental model.
Full runnable HTML for Step 40 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 40: Debug Grid systematically</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.page{display:grid;grid-template-columns:220px minmax(0,1fr);gap:12px;outline:3px dashed #c43}.side,.main{outline:2px solid #1670b5;padding:14px;background:white}.main{min-width:0;overflow-wrap:anywhere}
</style>
</head>
<body>
<div class="page"><aside class="side">Sidebar</aside><main class="main">VeryLongUnbrokenContentThatWouldOtherwiseTryToForceTheTrackWiderThanExpected_1234567890</main></div>
</body>
</html>Phase E · Step 41
Use content-aware track sizes
Grid tracks can respond to both content and available space.
Smallest useful code
.page {
display:grid;
grid-template-columns:max-content minmax(0,1fr);
}What you should see
Run the full example below for the exact result. The diagram is only a mental model.
Full runnable HTML for Step 41 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 41: Use content-aware track sizes</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.page{display:grid;grid-template-columns:max-content minmax(0,1fr);gap:12px}.side,.main{padding:18px;border:2px solid #0b67b2;background:white}
</style>
</head>
<body>
<div class="page"><aside class="side">Menu item with natural width</aside><main class="main">The main column takes the remaining space.</main></div>
</body>
</html>Phase E · Step 42
Use clamp() for fluid sizing
Layout often works better when typography and spacing also scale fluidly.
Smallest useful code
h1 {
font-size:clamp(2rem, 6vw, 5rem);
}
.wrapper {
padding:clamp(16px, 4vw, 56px);
}What you should see
Run the full example below for the exact result. The diagram is only a mental model.
Full runnable HTML for Step 42 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 42: Use clamp() for fluid sizing</title>
<style>
body{margin:0;font-family:Arial,sans-serif}.wrapper{padding:clamp(16px,4vw,56px);background:#eaf6ff;min-height:100vh}.wrapper h1{font-size:clamp(2rem,6vw,5rem);margin:0 0 16px}.cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:clamp(10px,2vw,24px)}.card{padding:20px;background:white;border:2px solid #0b67b2}
</style>
</head>
<body>
<main class="wrapper"><h1>Fluid layout</h1><div class="cards"><div class="card">A</div><div class="card">B</div><div class="card">C</div></div></main>
</body>
</html>Phase E · Step 43
Understand subgrid
subgrid lets a nested grid reuse the parent’s track definition where supported.
Smallest useful code
.cards {
display:grid;
grid-template-columns:repeat(3,1fr);
}
.card {
display:grid;
grid-row:span 3;
grid-template-rows:subgrid;
}What you should see
Run the full example below for the exact result. The diagram is only a mental model.
Full runnable HTML for Step 43 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 43: Understand subgrid</title>
<style>
body{font-family:Arial,sans-serif;padding:24px}.cards{display:grid;grid-template-columns:repeat(3,1fr);gap:12px}.card{display:grid;grid-template-rows:auto 1fr auto;gap:8px;padding:16px;border:2px solid #0b67b2;background:white}@supports(grid-template-rows:subgrid){.cards{grid-auto-rows:auto}.card{grid-row:span 3;grid-template-rows:subgrid}}@media(max-width:700px){.cards{grid-template-columns:1fr}}
</style>
</head>
<body>
<div class="cards"><article class="card"><h2>Short title</h2><p>Short text.</p><button>Open</button></article><article class="card"><h2>A much longer title that wraps</h2><p>More text in this card to create a different natural height.</p><button>Open</button></article><article class="card"><h2>Third</h2><p>Text.</p><button>Open</button></article></div>
</body>
</html>Phase E · Step 44
Accessibility: visual layout must not destroy meaning
Good layout keeps the source order logical.
Smallest useful code
<header>...</header>
<nav>...</nav>
<main>...</main>
<aside>...</aside>
<footer>...</footer>What you should see
Run the full example below for the exact result. The diagram is only a mental model.
Full runnable HTML for Step 44 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 44: Accessibility: visual layout must not destroy meaning</title>
<style>
body{margin:0;font-family:Arial,sans-serif}.page{display:grid;grid-template-columns:1fr 260px;grid-template-areas:"head head" "main side" "foot foot";gap:12px;padding:16px}.box{padding:18px;border:2px solid #0b67b2;background:white}header{grid-area:head}main{grid-area:main}aside{grid-area:side}footer{grid-area:foot}@media(max-width:700px){.page{grid-template-columns:1fr;grid-template-areas:"head" "main" "side" "foot"}}
</style>
</head>
<body>
<div class="page"><header class="box">Header and navigation</header><main class="box"><h1>Main content first</h1><p>The important reading content remains logically before the sidebar.</p></main><aside class="box">Supporting information</aside><footer class="box">Footer</footer></div>
</body>
</html>Phase F
Infinity Project
Design from a layout plan instead of memorising properties
Phase F · Step 45
Capstone: build from a layout plan
At infinity, you choose containers and layout systems deliberately.
Smallest useful code
/* 1. Shell */
.app { display:grid; grid-template-columns:230px minmax(0,1fr); }
/* 2. Toolbar */
.toolbar { display:flex; justify-content:space-between; flex-wrap:wrap; }
/* 3. Cards */
.cards { display:grid; grid-template-columns:repeat(auto-fit,minmax(170px,1fr)); }What you should see
Run the full example below for the exact result. The diagram is only a mental model.
Full runnable HTML for Step 45 — open/collapse
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Step 45: Capstone: build from a layout plan</title>
<style>
body{margin:0;font-family:Arial,sans-serif;background:#f4f7fa;color:#1e3040}.app{display:grid;grid-template-columns:230px minmax(0,1fr);min-height:100vh}.sidebar{padding:22px;background:#17324d;color:white}.main{padding:22px}.toolbar{display:flex;justify-content:space-between;align-items:center;gap:12px;flex-wrap:wrap}.actions{display:flex;gap:8px;flex-wrap:wrap}.cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(170px,1fr));gap:14px;margin:18px 0}.card,.panel{background:white;border:1px solid #d2dfe8;border-radius:12px;padding:18px}.content{display:grid;grid-template-columns:minmax(0,2fr) minmax(240px,1fr);gap:14px}.list{display:grid;gap:10px}.list>div{padding:12px;background:#eef6fb;border-radius:8px}@media(max-width:820px){.app{grid-template-columns:1fr}.sidebar{display:none}.content{grid-template-columns:1fr}}
</style>
</head>
<body>
<div class="app"><aside class="sidebar"><h2>Learn</h2><p>Dashboard</p><p>Lessons</p><p>Projects</p><p>Profile</p></aside><main class="main"><div class="toolbar"><div><small>Welcome back</small><h1>Learning Dashboard</h1></div><div class="actions"><button>Search</button><button>Share</button><button>New Project</button></div></div><section class="cards"><div class="card"><strong>12</strong><br>Lessons</div><div class="card"><strong>8</strong><br>Projects</div><div class="card"><strong>72%</strong><br>Progress</div><div class="card"><strong>4</strong><br>Challenges</div></section><section class="content"><article class="panel"><h2>Current lesson</h2><p>Build a responsive page from containers. Decide whether each container needs one-dimensional or two-dimensional control.</p><div class="list"><div>1. Identify the parent</div><div>2. Identify its direct children</div><div>3. Choose Flex or Grid</div><div>4. Add responsiveness</div></div></article><aside class="panel"><h2>Next</h2><p>Rebuild this layout without looking at the CSS.</p></aside></section></main></div>
</body>
</html>Fast reference
Which element receives which property?
Flex parent
display:flex, flex-direction, flex-wrap, justify-content, align-items, align-content, gapFlex child
flex, flex-grow, flex-shrink, flex-basis, align-self, orderGrid parent
display:grid, grid-template-columns, grid-template-rows, grid-template-areas, grid-auto-flow, place-items, gapGrid child
grid-column, grid-row, grid-area, justify-self, align-selfInfinity
You can now design a layout instead of copying one
The useful meaning of “∞” is not knowing every CSS property. It is being able to look at a page, divide it into containers, choose the right layout system for each container, make it responsive, and debug it when content or screen size changes.
1. Draw containers
Header, sidebar, toolbar, cards, article, footer.2. Ask one axis or two?
One main row/column → Flexbox. Explicit rows + columns → Grid.3. Prefer fluid rules
Usefr, minmax(), wrapping and useful minimums before hard-coded widths everywhere.