Design mobile-first and adapt layouts at each breakpoint with sm:, md:, lg:, and container queries.
Why: every utility can be prefixed with a breakpoint — sm: (640px), md: (768px), lg: (1024px), xl: (1280px), 2xl: (1536px) — meaning "apply this at this width and up". Unprefixed classes apply to every size, so you start with the mobile layout and layer on changes for larger screens.
<!-- Breakpoints: sm 640px · md 768px · lg 1024px · xl 1280px · 2xl 1536px -->
<!-- Unprefixed utilities apply at every size (the mobile-first base) -->
<p class="text-sm md:text-base lg:text-lg">
Small text on mobile, larger on tablets and desktops
</p>
<!-- Stack a column on mobile, switch to a row at md and up -->
<div class="flex flex-col gap-4 md:flex-row">
<div class="rounded bg-indigo-100 p-4">Sidebar</div>
<div class="rounded bg-slate-100 p-4">Content</div>
</div>
<!-- Hide on mobile, show from md and up -->
<nav class="hidden md:block">Desktop navigation</nav>By doing: this grid uses grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 — one column on phones, two on tablets, three on desktops. The preview shows the mobile (base) layout; copy this out and resize your browser to see it adapt.
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
<div class="rounded-lg bg-slate-100 p-4 text-center">
<p class="font-semibold">Fast</p>
<p class="text-sm text-slate-500">Optimized builds</p>
</div>
<div class="rounded-lg bg-slate-100 p-4 text-center">
<p class="font-semibold">Secure</p>
<p class="text-sm text-slate-500">Sandboxed by default</p>
</div>
<div class="rounded-lg bg-slate-100 p-4 text-center">
<p class="font-semibold">Flexible</p>
<p class="text-sm text-slate-500">Works everywhere</p>
</div>
</div>Why: @container lets a child react to the size of its parent container instead of the viewport — great for components reused at different widths (sidebars, dashboard panels). Mark the parent with @container and prefix child utilities with @sm:, @md:, etc. Both boxes below are visible at once, so you can compare a narrow and a wide container side by side.
<div class="space-y-4 p-4">
<div class="@container w-40 rounded border border-slate-300 p-2">
<div class="flex flex-col gap-2 @sm:flex-row">
<div class="h-10 w-10 shrink-0 rounded bg-indigo-500"></div>
<p class="text-xs">Narrow container — stacked</p>
</div>
</div>
<div class="@container w-80 rounded border border-slate-300 p-2">
<div class="flex flex-col gap-2 @sm:flex-row">
<div class="h-10 w-10 shrink-0 rounded bg-indigo-500"></div>
<p class="text-xs">Wide container — side by side once it passes the @sm container size</p>
</div>
</div>
</div>Why: min-[...] and max-[...] let you set a custom breakpoint for one-off cases. max-md: applies a utility below a breakpoint instead of above it — useful for "mobile only" overrides without writing a separate media query.
<!-- Custom breakpoint at exactly 850px -->
<div class="hidden min-[850px]:block">
Visible only at 850px and wider
</div>
<!-- Apply a style only below the md breakpoint (max-width: 767.98px) -->
<div class="max-md:bg-amber-100 md:bg-white">
Highlighted on small screens, plain on md and up
</div>
<!-- Combine a min and max for a range -->
<div class="hidden md:max-lg:block">
Visible only between md and lg
</div>