Build websites that look great on every screen β from smartphones to 4K monitors β using mobile-first design, media queries, fluid typography, and responsive images.
Background
Over 60% of web traffic comes from mobile devices. Responsive design isn't optional β it's the baseline. CSS provides powerful tools: viewport meta tag, @media queries, clamp(), srcset, and CSS custom properties. This lab covers all of them.
π‘ Mobile-first means writing min-width media queries, not max-width. Start with the simplest layout (mobile) and progressively add complexity for larger screens. This results in leaner CSS and forces content prioritization.
πΈ Verified Output:
Step 2: Media Queries & Breakpoints
Write this file:
π‘ Common breakpoints: 640px (small tablet), 768px (tablet), 1024px (laptop), 1280px (desktop), 1536px (large). You don't need to use all of them β use breakpoints where your content naturally breaks, not based on device sizes.
πΈ Verified Output:
Step 3: Fluid Typography with clamp()
Write this file:
π‘ clamp(min, preferred, max) eliminates most font-size media queries. clamp(1rem, 2.5vw, 1.5rem) means: never smaller than 1rem, scale with viewport width, never larger than 1.5rem. vw = 1% of viewport width β great for fluid scaling.
πΈ Verified Output:
Step 4: Responsive Images
Write this file:
π‘ srcset + sizes tells the browser about multiple image versions and hints about display size. The browser then picks the optimal one based on screen size AND pixel density. picture element lets you serve completely different image crops for different screens β "art direction."
πΈ Verified Output:
Step 5: Breakpoint System
Write this file:
π‘ Breakpoints are about content, not devices. Don't say "this is the iPhone breakpoint" β say "at this width, my content starts to break." Add a breakpoint when the layout looks wrong, not based on device specs. Fewer breakpoints = simpler CSS.
πΈ Verified Output:
Step 6: Responsive Navigation
Write this file:
π‘ The hamburger pattern: Mobile shows a toggle button; desktop shows links inline. display: none hides links on mobile, display: flex shows them on desktop. One JavaScript toggle class handles the mobile open/close state.
πΈ Verified Output:
Step 7: CSS Custom Properties for Responsive Theming
Write this file:
π‘ CSS variables in media queries β update the variable, everything using it updates automatically. This is the DRY (Don't Repeat Yourself) principle applied to responsive design. Define spacing/typography scales as variables, adjust them at breakpoints.
π‘ Capstone recap: This landing page applies every technique from this lab: viewport meta, mobile-first CSS, clamp() typography, CSS variables, responsive grid (auto-fit), and a responsive navigation. The --pad variable alone eliminates 6+ repeated media query blocks.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Mobile First</title>
<style>
/* MOBILE FIRST: styles here apply to ALL screen sizes */
body {
font-family: sans-serif;
padding: 16px;
font-size: 16px;
background: #f8f9fa;
}
.card {
background: white;
border-radius: 8px;
padding: 20px;
margin-bottom: 16px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
/* TABLET: add styles for 600px and above */
@media (min-width: 600px) {
body { padding: 24px; }
.card { padding: 28px; }
}
/* DESKTOP: add styles for 1024px and above */
@media (min-width: 1024px) {
body { max-width: 1200px; margin: 0 auto; padding: 40px; }
}
</style>
</head>
<body>
<h1>Mobile-First Design</h1>
<div class="card">
<h2>What is Mobile-First?</h2>
<p>Start with mobile CSS as the base. Use min-width media queries to progressively enhance for larger screens. This approach is better than max-width (desktop-first) because it forces you to prioritize content over decoration.</p>
</div>
<div class="card">
<h2>The Viewport Meta Tag</h2>
<p>Without <code><meta name="viewport"></code>, mobile browsers render the page at 980px and scale it down, making text tiny. This tag tells the browser to use the device's actual width.</p>
</div>
</body>
</html>