After this lesson, you will be able to: Build responsive layouts that work from a 320px phone screen up to a 1920px desktop using Tailwind's mobile-first breakpoint system, recognize when to use fluid typography with clamp(), and ship pages that don't break under DevTools' device-mode resizing.
Roughly 60% of global web traffic in 2025 comes from a phone. A page that only works on a 1440px laptop is broken before it's launched. Responsive design used to mean writing media queries — verbose, easy to forget, hard to scan. Tailwind replaces media queries with prefixes: `md:flex` means 'apply flex from the medium breakpoint up.' This lesson takes you from zero responsive sense to fluent in Tailwind's breakpoint mental model.
Mobile-first means: write the small-screen styles as your default, then progressively add larger-screen overrides. There are two reasons to work this way. First, the math — most users hit your page from a phone, so the default styles should be the ones they see. Second, the constraint — designing for the smallest viewport forces simpler decisions. If your content can't fit on a phone, that's usually a content problem, not a layout problem. Tailwind is opinionated here: unprefixed utilities are the smallest-screen default. `md:` and up are progressive enhancements.
Five breakpoints cover the device landscape: `sm` (640px, large phones in landscape), `md` (768px, tablets), `lg` (1024px, small laptops), `xl` (1280px, larger laptops), `2xl` (1536px, big desktops). These are min-widths — `md:flex` means 'flex applies at 768px AND UP.' To target a screen-size range, combine prefixes: `md:flex lg:grid` means flex from 768-1023px, grid from 1024px up. There is no `xs:` prefix because the default unprefixed style IS the smallest-screen style. That's the mobile-first guarantee.
A common pattern: stacked on mobile, side-by-side from medium up. The default `flex flex-col` is the mobile layout. The `md:flex-row` overrides direction from 768px up. Reads from small → large as you scan left → right.
<div class="flex flex-col md:flex-row gap-4"><aside class="w-full md:w-64 bg-gray-100 p-4">Sidebar</aside><main class="flex-1 p-4">Main content</main></div><!-- Multi-column grid that adapts --><div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4"><div>Card 1</div><div>Card 2</div><div>Card 3</div></div><!-- Different typography per breakpoint --><h1 class="text-2xl md:text-4xl lg:text-5xl font-bold">Scales with the viewport</h1>
**Stack on mobile, row on desktop** — `flex flex-col md:flex-row`. The single most common pattern; works for headers, cards, sidebars. **Hide on mobile, show on desktop (and vice versa)** — `hidden md:block` shows from medium up; `block md:hidden` shows below medium. Use sparingly — the better answer is usually a layout change, not hiding content. **Different column counts** — `grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4` is the bread-and-butter responsive grid. **Wider gutters on bigger screens** — `gap-2 md:gap-4 lg:gap-6` keeps spacing proportional to the viewport.
A header that stacks on phones, becomes a row on tablets, and adds a search bar on desktops. Three breakpoints used in one component.
<header class="flex flex-col md:flex-row md:items-center md:justify-betweengap-3 md:gap-6p-4 md:p-6border-b border-gray-200"><a href="/" class="text-lg font-bold">BiTree</a><!-- Search: hidden on mobile, visible from lg up --><inputtype="search"placeholder="Search..."class="hidden lg:block flex-1 max-w-md border rounded-lg px-3 py-2"/><nav class="flex gap-4 text-sm"><a href="/curriculum">Curriculum</a><a href="/pricing">Pricing</a><a href="/login" class="font-semibold">Sign in</a></nav></header>
Breakpoint-stepped typography (`text-2xl md:text-4xl lg:text-5xl`) jumps at the breakpoint boundaries. For headings, that jump can feel jarring. CSS's `clamp(min, preferred, max)` function gives you continuous scaling — a single declaration that gracefully interpolates between a minimum and maximum size as the viewport changes. `font-size: clamp(1.5rem, 4vw, 3.5rem)` says: never smaller than 1.5rem, never larger than 3.5rem, scale linearly with 4% of viewport width in between. This is overkill for body text but excellent for hero headlines.
Media queries respond to the viewport. Container queries respond to the parent container's width — which is what you actually want for reusable components. A card that needs to switch layouts at 400px wide should not depend on the page being 1024px wide. Container queries shipped to all evergreen browsers in 2023 and Tailwind v3.2+ supports them via the `@container` plugin and `@md:` style prefixes. Mention them in interviews — using them shows you're tracking the modern CSS surface — but you can still ship great apps without them.
The starter is a two-column layout that looks fine on desktop and broken on mobile (it stays as two narrow columns instead of stacking). Apply Tailwind's mobile-first prefixes so it: stacks vertically below `md`, becomes a two-column row from `md` up, and uses `md:gap-6` for slightly wider spacing on bigger screens. Required patterns check for `flex-col`, `md:flex-row`, and `gap-` utilities.
Remember: Tailwind prefixes are min-width — they apply from that size up.
Sign in and purchase access to unlock this lesson.