Phase 2 — CSS
Lesson 0008 • Intermediate

Responsive Design

Over 60% of web traffic comes from mobile devices. If your site only looks good on a laptop, you've already lost most of your users. Responsive design isn't a bonus feature — it's the baseline. Every professional site you've ever used is responsive. After this lesson, yours will be too.

1. The Viewport Meta Tag

Every HTML page you've created already has this line in the <head>:

index.html
<meta name="viewport" content="width=device-width, initial-scale=1.0">

Without this tag, mobile browsers render pages at ~980px wide and then zoom out to fit — making everything tiny and unreadable. This tag tells the browser: "Match the viewport width to the device width. Don't zoom out." (MDN: Viewport meta tag)

⚠️ Never omit this tag Without it, media queries don't work on mobile. The browser thinks the viewport is 980px wide regardless of the actual screen. This is the #1 reason "my responsive design doesn't work on my phone."

2. Mobile-First: The Right Way to Think

There are two approaches to responsive design:

Approach Base Styles For Media Queries Add
Desktop-First ❌ Large screens max-width to shrink down
Mobile-First ✅ Small screens min-width to expand up

Why Mobile-First Wins

1. Simpler base CSS. A mobile layout is usually a single column — the simplest structure. You start simple and add complexity.
2. Progressive enhancement. Small screens get fast-loading minimal CSS. Larger screens get extra features. If a media query fails, the site still works.
3. Industry standard. Every modern CSS framework (Tailwind, Bootstrap) is mobile-first. Every professional developer thinks this way.

(web.dev: Responsive web design basics)
style.css — Mobile-First Pattern
/* BASE: Mobile styles (no media query needed) */
.cards {
  display: grid;
  grid-template-columns: 1fr;  /* Single column on mobile */
  gap: 16px;
}

/* TABLET: 2 columns at 600px+ */
@media (min-width: 600px) {
  .cards {
    grid-template-columns: 1fr 1fr;
  }
}

/* DESKTOP: 3 columns at 1024px+ */
@media (min-width: 1024px) {
  .cards {
    grid-template-columns: 1fr 1fr 1fr;
  }
}

Notice: the base styles have no media query. They're the default. Media queries only add overrides for larger screens using min-width.

3. Media Queries: The Syntax

A media query is a CSS @media rule that applies styles only when a condition is true:

style.css
@media (min-width: 768px) {
  /* These styles ONLY apply when viewport is 768px or wider */
  .sidebar {
    display: block;
  }
}

The rules inside the @media block are ignored when the condition is false. When the viewport meets the condition, those rules activate and override base styles (normal CSS cascade rules apply). (MDN: Using media queries)

Common Breakpoints

There's no "official" set, but these are the most widely used:

Breakpoint Target Usage
480px Large phones Rarely needed if base styles are mobile-first
600px Small tablets / landscape phones Switch from 1-column to 2-column
768px Tablets Show sidebar, expand navigation
1024px Small desktops / laptops Full desktop layout
1280px Large desktops Extra-wide layouts, max-width containers
💡 Design for content, not devices Don't memorize breakpoints. Resize your browser slowly. When the layout breaks, add a breakpoint there. Let your content decide the breakpoints, not arbitrary device widths. (Kevin Powell: Stop using so many media queries)

4. See It In Action

Click the viewport buttons below to see how media queries change the layout at different screen sizes:

At 320px: single column. At 480px: 2 columns. At 768px: 3 columns. The base CSS is mobile-first — the @media rules only add columns as space permits.

5. Fluid Typography with clamp()

Hard-coding font sizes creates problems. 3rem looks great on desktop but overwhelms a phone screen. You could use media queries, but there's a better way — clamp():

style.css
h1 {
  /* clamp(minimum, preferred, maximum) */
  font-size: clamp(1.8rem, 4vw + 1rem, 3.5rem);
}

p {
  font-size: clamp(0.95rem, 1.5vw + 0.5rem, 1.15rem);
}

How clamp() works:

The result: smooth, proportional scaling with no media queries and no jumps. The browser calculates the right size for every viewport width automatically. (MDN: clamp())

💡 clamp() works on anything, not just fonts You can use it for padding, margins, widths — any numeric CSS property. padding: clamp(1rem, 3vw, 3rem) gives you fluid spacing.

6. Responsive Images

By default, images render at their intrinsic pixel size. A 2000px-wide photo will overflow a 375px phone screen. The fix is one CSS rule:

style.css — Add this to your CSS reset
img {
  max-width: 100%;
  height: auto;
  display: block;
}

This single rule should be in every CSS reset you ever write. It makes all images fluid by default. (MDN: Images in CSS)

The srcset Attribute (Performance)

For production sites, you'll want to serve different image sizes to different devices — no point sending a 2MB desktop image to a phone on 4G:

index.html
<img
  src="photo-800.jpg"
  srcset="photo-400.jpg 400w,
         photo-800.jpg 800w,
         photo-1200.jpg 1200w"
  sizes="(max-width: 600px) 100vw,
        (max-width: 1024px) 50vw,
        33vw"
  alt="Project screenshot"
>

The browser selects the best image based on the device's viewport width and pixel density. You don't need to master srcset right now — just know it exists. You'll use it in production projects later. (MDN: Responsive images)

7. Common Responsive Patterns

Pattern 1: Hidden Sidebar on Mobile

style.css
/* Mobile: sidebar hidden */
.sidebar {
  display: none;
}

/* Desktop: show sidebar */
@media (min-width: 768px) {
  .page {
    display: grid;
    grid-template-columns: 250px 1fr;
  }
  .sidebar {
    display: block;
  }
}

Pattern 2: Stack Navigation on Mobile

style.css
/* Mobile: stack nav vertically */
.nav {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

/* Desktop: horizontal nav */
@media (min-width: 768px) {
  .nav {
    flex-direction: row;
    justify-content: space-between;
    align-items: center;
  }
}

Pattern 3: Fluid Container with Max-Width

style.css
.container {
  width: 100%;
  max-width: 1200px;
  margin: 0 auto;
  padding: 0 clamp(1rem, 3vw, 3rem);
}

This is the universal container pattern. Full width on mobile, capped at 1200px on desktop, auto-centered, with fluid padding that scales between 1rem and 3rem. You'll use this on every project.

Pattern 4: Responsive Grid (No Media Queries)

style.css
/* You learned this in Lesson 7 — now you see why it matters */
.cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 24px;
}

This was introduced in Lesson 7, but now you understand why it's so powerful — it's a responsive pattern that doesn't need a single media query.

8. Responsive Units: The Full Picture

You've seen px, rem, %, and now vw. Here's when to use each:

Unit Relative To Best For
px Nothing (absolute) Borders, shadows, thin lines — things that shouldn't scale
rem Root font size (usually 16px) Font sizes, spacing, most dimensions — the default choice
em Parent element's font size Component-internal spacing (padding relative to text size)
% Parent element's size Widths inside containers, flexible grid tracks
vw / vh Viewport width / height Full-screen sections, fluid typography inside clamp()
fr Remaining space in grid CSS Grid column/row sizing only
💡 The Rule of Thumb Use rem for almost everything. Use px for borders and box-shadows. Use % for widths. Use vw only inside clamp(). Use fr only in Grid. When in doubt, use rem.

9. Testing Responsiveness

You don't need a phone to test mobile layouts. Every browser has built-in device simulation:

  1. Open DevTools: Press F12 or Ctrl + Shift + I
  2. Toggle device toolbar: Press Ctrl + Shift + M (or click the phone/tablet icon)
  3. Select a device: Choose "iPhone 14", "iPad", etc. from the dropdown
  4. Drag the handles: Resize the viewport freely to find where your layout breaks
⚠️ DevTools ≠ a real phone DevTools simulates viewport size, not touch behavior, performance, or rendering differences. Always test on a real device before shipping to production. But for development, DevTools is your primary tool.

10. Test Your Knowledge

Quiz: Responsive Design

In mobile-first CSS, what type of media query do you use to add styles for larger screens?
Correct. Mobile-first means your base CSS is for small screens, and you use min-width to layer on styles for larger viewports.
Not quite. Mobile-first uses min-width: "at a minimum of X width, apply these styles." Desktop-first uses max-width.
What does the viewport meta tag width=device-width do?
Correct. Without it, mobile browsers assume ~980px width. This tag tells the browser to use the real device width.
The viewport meta tag sets the CSS viewport width to match the physical device width, enabling media queries to work correctly on mobile.
What does clamp(1rem, 3vw + 0.5rem, 2rem) do?
Correct. The value scales with viewport width (3vw + 0.5rem) but never drops below 1rem or exceeds 2rem.
clamp(min, preferred, max) means: use the preferred value, but never go below min or above max. It creates smooth, bounded scaling.
Why is max-width: 100% essential on images?
Correct. Without it, a 2000px-wide image overflows a 375px phone screen. max-width: 100% constrains images to their container.
Images render at their intrinsic size by default. max-width: 100% caps them at the container width, preventing horizontal overflow.
Where do you put base (mobile) styles in a mobile-first stylesheet?
Correct. Mobile-first means base styles (no media query) are for mobile. @media (min-width: ...) adds overrides for larger screens.
In mobile-first CSS, base styles are the mobile styles — they need no media query. Media queries only add complexity for larger screens.
Which approach builds a responsive grid without any media queries?
Correct. repeat(auto-fill, minmax(...)) creates as many columns as fit, auto-reflowing as the viewport resizes — no media queries needed.
The pattern from Lesson 7: repeat(auto-fill, minmax(250px, 1fr)) creates columns that are at least 250px, fitting as many as possible — fully responsive without media queries.
–

Quiz Complete!

Review any concepts you got wrong using the Responsive Design cheatsheet.

11. Retrieval Practice: Fill In The Blanks

Write from memory. If you can't recall it, that's the point — effortful retrieval is how knowledge sticks.

/* Mobile-first responsive card grid */
.cards {
  display: ;
  grid-template-columns: ;
  gap: 16px;
}
@media ( : 600px) {
  .cards { grid-template-columns: ; }
}
@media ( : 1024px) {
  .cards { grid-template-columns: ; }
}

12. Build Challenge: Responsive Portfolio

This is the capstone of Phase 2 (CSS). Take everything from Lessons 4–8 and build a fully responsive portfolio site from scratch. No templates. No copying. Your design, your code.

  1. Create practices/lesson8-portfolio.html and practices/lesson8-style.css
  2. Start mobile-first — write all base styles for a 320px screen first:
    • Single-column layout
    • Stacked navigation (logo above links)
    • Full-width cards
  3. Add a tablet breakpoint at 600px:
    • 2-column card grid
    • Horizontal navigation
  4. Add a desktop breakpoint at 1024px:
    • 3-column card grid
    • Max-width container (1200px) with auto margins
    • Optional: sidebar layout
  5. Apply these responsive techniques:
    • Fluid typography: clamp() on h1, h2, and body text
    • Responsive images: max-width: 100%; height: auto
    • Fluid container padding: padding: 0 clamp(1rem, 3vw, 3rem)
    • CSS Grid or Flexbox — your choice per component
  6. Test in DevTools: resize from 320px to 1400px. No horizontal scrollbars should appear at any width.
⚠️ This Is the Test This challenge combines everything from 5 lessons: CSS properties (L4), display/position/transitions (L5), Flexbox (L6), Grid (L7), and responsive design (L8). If you can build this without looking at old lessons, your CSS foundation is solid. Use the reference sheets if you need property names: CSS Foundations, Flexbox, Grid, Responsive Design.

Primary Sources: web.dev: Responsive web design basics is Google's definitive guide. Also: MDN: Responsive design and Kevin Powell's responsive design playlist.

Finished the build? Type /teach and show me your portfolio. I'll review your responsive breakpoints, check for horizontal overflow, and verify mobile-first structure. After this, we move on to Phase 3: JavaScript.

💬 Questions? Ask your teacher. Media queries, clamp(), breakpoint strategy, viewport units — if anything feels fuzzy, ask me now. This is the last CSS lesson before JavaScript. Don't carry uncertainty into the next phase.