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">LastWrite</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.