Learn With Champak · Detailed 0 → ∞

Flexbox + Grid

Start before Flexbox: HTML, CSS, boxes, parents and normal flow. Then move one idea at a time through Flexbox, Grid, responsive layouts, nesting, debugging and a complete dashboard. Every stage has a complete runnable HTML option.

46 stagesAbsolute zero firstFull HTML every stageFlexboxGridResponsiveProjects
Practice Editor

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.

Core mental model: find the parent → identify its direct children → decide whether the relationship is mainly one-dimensional (Flexbox) or two-dimensional (Grid).

Every step contains

  1. One concept
  2. Smallest useful code
  3. Result to expect
  4. A change-it-yourself task
  5. Complete runnable HTML
  6. Link back to the embedded editor

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 tab

Phase A

Absolute Zero

HTML, CSS, boxes, parents and normal flow

0

Phase A · Step 0

What are HTML and CSS?

HTML creates the things. CSS changes how they look and where they sit.

Before Flexbox or Grid, understand the two jobs. HTML gives us headings, paragraphs and boxes. CSS selects those things and styles them.

Smallest useful code

Focus on this
<h1>Hello</h1>
<p>This is HTML.</p>

What you should see

Parent / layout
Child A
Child B

Run the full example below for the exact result. The diagram is only a mental model.

Change this: Change the heading text, then change the color in CSS.
Important: Flexbox and Grid are CSS layout systems. We will reach them gradually.
Full runnable HTML for Step 0 — open/collapse
Complete file: HTML + CSS
<!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>
1

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

Focus on this
<div>My first box</div>

What you should see

Parent / layout
Child A
Child 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
Complete file: HTML + CSS
<!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>
2

Phase 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

Focus on this
<div class="box">A</div>
<div class="box">B</div>

What you should see

Parent / layout
Child A
Child 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
Complete file: HTML + CSS
<!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>
3

Phase 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

Focus on this
.box {
  width: 220px;
  padding: 20px;
  border: 4px solid #0b67b2;
  margin: 20px;
}

What you should see

Parent / layout
Child A
Child 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
Complete file: HTML + CSS
<!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>
4

Phase 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

Focus on this
<div class="parent">
  <div class="child">A</div>
  <div class="child">B</div>
  <div class="child">C</div>
</div>

What you should see

Parent / layout
Child A
Child 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
Complete file: HTML + CSS
<!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>
5

Phase 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

Focus on this
.parent { border: 3px dashed #7997ad; }
.child { padding: 16px; border: 2px solid #0b67b2; }

What you should see

Parent / layout
Child A
Child 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
Complete file: HTML + CSS
<!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

6

Phase 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

Focus on this
.parent {
  display: flex;
}

What you should see

Parent / layout
Child A
Child 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
Complete file: HTML + CSS
<!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>
7

Phase 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

Focus on this
.parent {
  display: flex;
  /* main axis → */
  /* cross axis ↓ */
}

What you should see

Parent / layout
Child A
Child 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
Complete file: HTML + CSS
<!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>
8

Phase 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

Focus on this
.parent {
  display: flex;
  flex-direction: column;
}

What you should see

Parent / layout
Child A
Child 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
Complete file: HTML + CSS
<!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>
9

Phase 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

Focus on this
.parent {
  display: flex;
  gap: 16px;
}

What you should see

Parent / layout
Child A
Child 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
Complete file: HTML + CSS
<!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>
10

Phase 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

Focus on this
.parent {
  display: flex;
  justify-content: space-between;
}

What you should see

Parent / layout
Child A
Child 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
Complete file: HTML + CSS
<!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>
11

Phase 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

Focus on this
.parent {
  display: flex;
  min-height: 220px;
  align-items: center;
}

What you should see

Parent / layout
Child A
Child 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
Complete file: HTML + CSS
<!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>
12

Phase 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

Focus on this
.parent {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 300px;
}

What you should see

Parent / layout
Child A
Child 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
Complete file: HTML + CSS
<!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>
13

Phase 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

Focus on this
.parent {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}
.child { width: 180px; }

What you should see

Parent / layout
Child A
Child 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
Complete file: HTML + CSS
<!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>
14

Phase 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

Focus on this
.child {
  flex-basis: 180px;
}

What you should see

Parent / layout
Child A
Child 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
Complete file: HTML + CSS
<!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>
15

Phase 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

Focus on this
.a { flex-grow: 1; }
.b { flex-grow: 2; }
.c { flex-grow: 1; }

What you should see

Parent / layout
Child A
Child 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
Complete file: HTML + CSS
<!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>
16

Phase 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

Focus on this
.fixed {
  width: 240px;
  flex-shrink: 0;
}

What you should see

Parent / layout
Child A
Child 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
Complete file: HTML + CSS
<!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>
17

Phase 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

Focus on this
.child {
  flex: 1 1 200px;
}

What you should see

Parent / layout
Child A
Child 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
Complete file: HTML + CSS
<!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>
18

Phase 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

Focus on this
.parent { align-items: flex-start; }
.special { align-self: flex-end; }

What you should see

Parent / layout
Child A
Child 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
Complete file: HTML + CSS
<!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>
19

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.

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

Focus on this
.first-visually { order: -1; }

What you should see

Parent / layout
Child A
Child 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
Complete file: HTML + CSS
<!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>
20

Phase 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

Focus on this
.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 / layout
Child A
Child 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
Complete file: HTML + CSS
<!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

21

Phase 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

Focus on this
.parent {
  display: grid;
  grid-template-columns: 1fr 1fr;
}

What you should see

Parent / layout
Child A
Child 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
Complete file: HTML + CSS
<!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>
22

Phase 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

Focus on this
.grid {
  display:grid;
  grid-template-columns: 150px 250px;
}

What you should see

Parent / layout
Child A
Child 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
Complete file: HTML + CSS
<!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>
23

Phase 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

Focus on this
.grid {
  display:grid;
  grid-template-columns: 1fr 2fr;
  gap:12px;
}

What you should see

Parent / layout
Child A
Child 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
Complete file: HTML + CSS
<!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>
24

Phase 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

Focus on this
.grid {
  display:grid;
  grid-template-columns: repeat(4, 1fr);
}

What you should see

Parent / layout
Child A
Child 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
Complete file: HTML + CSS
<!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>
25

Phase 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

Focus on this
.grid {
  display:grid;
  grid-template-columns: repeat(3,1fr);
  grid-template-rows: 80px 140px;
  gap:12px;
}

What you should see

Parent / layout
Child A
Child 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
Complete file: HTML + CSS
<!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>
26

Phase 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

Focus on this
.grid {
  display:grid;
  grid-template-columns:repeat(3,1fr);
  grid-auto-rows:120px;
  place-items:center;
}

What you should see

Parent / layout
Child A
Child 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
Complete file: HTML + CSS
<!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>
27

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.

This automatic placement makes ordinary card collections very easy.

Smallest useful code

Focus on this
.grid {
  display:grid;
  grid-template-columns:repeat(3,1fr);
  gap:12px;
}

What you should see

Parent / layout
Child A
Child 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
Complete file: HTML + CSS
<!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>
28

Phase 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

Focus on this
.grid {
  display:grid;
  grid-template-columns:repeat(3, minmax(140px, 1fr));
}

What you should see

Parent / layout
Child A
Child 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
Complete file: HTML + CSS
<!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>
29

Phase 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

Focus on this
.grid {
  display:grid;
  grid-template-columns:repeat(auto-fit, minmax(180px, 1fr));
  gap:16px;
}

What you should see

Parent / layout
Child A
Child 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
Complete file: HTML + CSS
<!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>
30

Phase 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

Focus on this
.wide {
  grid-column: span 2;
}

What you should see

Parent / layout
Child A
Child 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
Complete file: HTML + CSS
<!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>
31

Phase 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

Focus on this
.header {
  grid-column: 1 / -1;
}

What you should see

Parent / layout
Child A
Child 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
Complete file: HTML + CSS
<!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>
32

Phase 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

Focus on this
.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 / layout
Child A
Child 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
Complete file: HTML + CSS
<!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>
33

Phase 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

Focus on this
.gallery {
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(160px,1fr));
  gap:14px;
}

What you should see

Parent / layout
Child A
Child 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
Complete file: HTML + CSS
<!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

34

Phase 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

Focus on this
.page {
  display:grid;
  grid-template-columns:220px 1fr;
}
@media (max-width:700px) {
  .page { grid-template-columns:1fr; }
}

What you should see

Parent / layout
Child A
Child 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
Complete file: HTML + CSS
<!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>
35

Phase 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

Focus on this
.page { display:grid; grid-template-columns:220px 1fr; }
.toolbar { display:flex; justify-content:space-between; gap:12px; }

What you should see

Parent / layout
Child A
Child 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
Complete file: HTML + CSS
<!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>
36

Phase 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

Focus on this
.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 / layout
Child A
Child 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
Complete file: HTML + CSS
<!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>
37

Phase 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

Focus on this
.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 / layout
Child A
Child 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
Complete file: HTML + CSS
<!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>
38

Phase 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

Focus on this
.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 / layout
Child A
Child 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
Complete file: HTML + CSS
<!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

39

Phase 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

Focus on this
/* Debug checklist */
.parent {
  outline:3px dashed red;
  display:flex;
}
.parent > * { outline:2px solid blue; }

What you should see

Parent / layout
Child A
Child 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
Complete file: HTML + CSS
<!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>
40

Phase 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

Focus on this
.page {
  display:grid;
  grid-template-columns:220px minmax(0,1fr);
}
.main { min-width:0; }

What you should see

Parent / layout
Child A
Child 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
Complete file: HTML + CSS
<!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>
41

Phase 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

Focus on this
.page {
  display:grid;
  grid-template-columns:max-content minmax(0,1fr);
}

What you should see

Parent / layout
Child A
Child 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
Complete file: HTML + CSS
<!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>
42

Phase 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

Focus on this
h1 {
  font-size:clamp(2rem, 6vw, 5rem);
}
.wrapper {
  padding:clamp(16px, 4vw, 56px);
}

What you should see

Parent / layout
Child A
Child 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
Complete file: HTML + CSS
<!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>
43

Phase 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

Focus on this
.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 / layout
Child A
Child 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
Complete file: HTML + CSS
<!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>
44

Phase 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

Focus on this
<header>...</header>
<nav>...</nav>
<main>...</main>
<aside>...</aside>
<footer>...</footer>

What you should see

Parent / layout
Child A
Child 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
Complete file: HTML + CSS
<!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

45

Phase 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

Focus on this
/* 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 / layout
Child A
Child 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
Complete file: HTML + CSS
<!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, gap

Flex child

flex, flex-grow, flex-shrink, flex-basis, align-self, order

Grid parent

display:grid, grid-template-columns, grid-template-rows, grid-template-areas, grid-auto-flow, place-items, gap

Grid 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.