Responsive Design with Tailwind CSS
Build responsive layouts with Tailwind CSS: mobile-first breakpoints, responsive utilities, container queries, and practical patterns for real-world responsive components.
What you'll learn
- ✓How Tailwind breakpoints and mobile-first design work
- ✓Responsive typography, spacing, and grid patterns
- ✓Container queries for component-level responsiveness
- ✓Building a responsive navbar, card grid, and dashboard
- ✓Common responsive pitfalls and how to avoid them
Prerequisites
- •Basic Tailwind CSS knowledge (utility classes)
- •Understanding of CSS flexbox and grid
- •HTML fundamentals
Tailwind CSS takes a mobile-first approach to responsive design. You write styles for mobile by default, then layer on changes at larger breakpoints. This means every utility class without a breakpoint prefix applies to all screen sizes, and prefixed utilities only kick in at that breakpoint and above.
Default breakpoints
Tailwind ships with five breakpoints:
| Prefix | Min width | Typical target |
|---|---|---|
sm | 640px | Large phones, small tablets |
md | 768px | Tablets |
lg | 1024px | Laptops |
xl | 1280px | Desktops |
2xl | 1536px | Large screens |
<!-- Mobile: single column -->
<!-- md and up: two columns -->
<!-- lg and up: three columns -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
<div class="bg-white p-4 rounded shadow">Card 1</div>
<div class="bg-white p-4 rounded shadow">Card 2</div>
<div class="bg-white p-4 rounded shadow">Card 3</div>
</div>
Mobile-first thinking
Write the mobile layout first, then add breakpoint prefixes for larger screens. This is the opposite of the “desktop first, then fix mobile” approach.
<!-- Start with mobile styles (no prefix) -->
<!-- Add tablet and desktop overrides -->
<section class="px-4 py-8 md:px-8 md:py-12 lg:px-16 lg:py-16">
<h1 class="text-2xl font-bold md:text-3xl lg:text-5xl">
Welcome to our platform
</h1>
<p class="mt-4 text-base text-gray-600 md:text-lg lg:text-xl lg:max-w-2xl">
Build something amazing with our tools and APIs.
</p>
<div class="mt-6 flex flex-col gap-3 sm:flex-row sm:gap-4">
<a href="/signup" class="rounded bg-blue-600 px-6 py-3 text-center text-white hover:bg-blue-700">
Get started
</a>
<a href="/docs" class="rounded border border-gray-300 px-6 py-3 text-center hover:bg-gray-50">
Read docs
</a>
</div>
</section>
On mobile: stacked layout, smaller text, full-width buttons stacked vertically. On tablet and up: more padding, larger text, buttons side by side.
Responsive navigation
A common pattern: horizontal nav on desktop, hamburger menu on mobile.
<nav class="bg-white shadow">
<div class="mx-auto max-w-7xl px-4">
<div class="flex h-16 items-center justify-between">
<!-- Logo -->
<a href="/" class="text-xl font-bold">Logo</a>
<!-- Desktop nav (hidden on mobile) -->
<div class="hidden md:flex md:items-center md:gap-6">
<a href="/products" class="text-gray-700 hover:text-blue-600">Products</a>
<a href="/pricing" class="text-gray-700 hover:text-blue-600">Pricing</a>
<a href="/docs" class="text-gray-700 hover:text-blue-600">Docs</a>
<a href="/login" class="rounded bg-blue-600 px-4 py-2 text-white hover:bg-blue-700">
Sign in
</a>
</div>
<!-- Mobile menu button (hidden on desktop) -->
<button class="md:hidden rounded p-2 hover:bg-gray-100" id="menu-btn">
<svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
</svg>
</button>
</div>
<!-- Mobile menu (shown when toggled) -->
<div class="md:hidden border-t py-3 hidden" id="mobile-menu">
<a href="/products" class="block py-2 text-gray-700">Products</a>
<a href="/pricing" class="block py-2 text-gray-700">Pricing</a>
<a href="/docs" class="block py-2 text-gray-700">Docs</a>
<a href="/login" class="mt-2 block rounded bg-blue-600 px-4 py-2 text-center text-white">
Sign in
</a>
</div>
</div>
</nav>
The hidden md:flex pattern hides the desktop nav on mobile and shows it from md up. The md:hidden pattern does the inverse for the hamburger button.
Responsive grid patterns
Dashboard layout
<div class="min-h-screen bg-gray-100">
<!-- Sidebar: hidden on mobile, fixed on desktop -->
<aside class="fixed inset-y-0 left-0 z-30 hidden w-64 bg-white shadow lg:block">
<div class="p-6">
<h2 class="text-lg font-bold">Dashboard</h2>
<nav class="mt-6 space-y-2">
<a href="#" class="block rounded px-3 py-2 bg-blue-50 text-blue-700">Overview</a>
<a href="#" class="block rounded px-3 py-2 text-gray-600 hover:bg-gray-50">Analytics</a>
<a href="#" class="block rounded px-3 py-2 text-gray-600 hover:bg-gray-50">Settings</a>
</nav>
</div>
</aside>
<!-- Main content: full width on mobile, offset on desktop -->
<main class="lg:ml-64">
<div class="p-4 md:p-6 lg:p-8">
<!-- Stats grid -->
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2 xl:grid-cols-4">
<div class="rounded-lg bg-white p-6 shadow">
<p class="text-sm text-gray-500">Revenue</p>
<p class="mt-1 text-2xl font-bold">$45,231</p>
</div>
<div class="rounded-lg bg-white p-6 shadow">
<p class="text-sm text-gray-500">Users</p>
<p class="mt-1 text-2xl font-bold">2,350</p>
</div>
<div class="rounded-lg bg-white p-6 shadow">
<p class="text-sm text-gray-500">Orders</p>
<p class="mt-1 text-2xl font-bold">1,247</p>
</div>
<div class="rounded-lg bg-white p-6 shadow">
<p class="text-sm text-gray-500">Conversion</p>
<p class="mt-1 text-2xl font-bold">3.2%</p>
</div>
</div>
<!-- Chart and table: stack on mobile, side by side on desktop -->
<div class="mt-6 grid grid-cols-1 gap-6 lg:grid-cols-3">
<div class="rounded-lg bg-white p-6 shadow lg:col-span-2">
<h3 class="font-semibold">Revenue Chart</h3>
<!-- chart goes here -->
</div>
<div class="rounded-lg bg-white p-6 shadow">
<h3 class="font-semibold">Recent Activity</h3>
<!-- activity list goes here -->
</div>
</div>
</div>
</main>
</div>
Product card grid
<div class="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
<article class="group overflow-hidden rounded-lg bg-white shadow transition hover:shadow-lg">
<div class="aspect-square overflow-hidden">
<img
src="/product.jpg"
alt="Product"
class="h-full w-full object-cover transition group-hover:scale-105"
/>
</div>
<div class="p-4">
<h3 class="font-semibold text-gray-900">Product Name</h3>
<p class="mt-1 text-sm text-gray-500 line-clamp-2">
A short description of the product that might be long.
</p>
<div class="mt-3 flex items-center justify-between">
<span class="text-lg font-bold text-blue-600">$29.99</span>
<button class="rounded bg-blue-600 px-3 py-1.5 text-sm text-white hover:bg-blue-700">
Add to cart
</button>
</div>
</div>
</article>
<!-- more cards -->
</div>
Responsive typography
<!-- Scale text with breakpoints -->
<h1 class="text-3xl font-bold sm:text-4xl md:text-5xl lg:text-6xl">
Big headline
</h1>
<!-- Responsive line length for readability -->
<p class="max-w-prose text-base md:text-lg">
Long paragraph text that should not stretch too wide on large screens.
The max-w-prose utility caps the width at 65 characters, which is
the optimal line length for reading.
</p>
Responsive visibility
Show and hide elements at different breakpoints.
<!-- Only visible on mobile -->
<div class="block sm:hidden">Mobile only content</div>
<!-- Hidden on mobile, visible from sm up -->
<div class="hidden sm:block">Tablet and desktop content</div>
<!-- Only visible on lg screens -->
<div class="hidden lg:block xl:hidden">Laptop only</div>
Container queries
Tailwind v3.4+ supports container queries, which let components respond to their container’s size rather than the viewport.
<!-- Mark the container -->
<div class="@container">
<div class="flex flex-col @md:flex-row @md:items-center gap-4">
<img src="/avatar.jpg" class="h-16 w-16 @md:h-20 @md:w-20 rounded-full" />
<div>
<h3 class="text-lg @md:text-xl font-semibold">User Name</h3>
<p class="text-sm text-gray-500 @md:text-base">Software Engineer</p>
</div>
</div>
</div>
Container queries are useful for reusable components that might appear in a sidebar (narrow) or main content area (wide). The component adapts to its container, not the viewport.
Custom breakpoints
Add custom breakpoints in tailwind.config.js:
// tailwind.config.js
module.exports = {
theme: {
screens: {
xs: "475px",
sm: "640px",
md: "768px",
lg: "1024px",
xl: "1280px",
"2xl": "1536px",
},
},
};
Or extend the defaults:
module.exports = {
theme: {
extend: {
screens: {
xs: "475px",
"3xl": "1920px",
},
},
},
};
Common mistakes
Designing desktop first. With Tailwind, unprefixed styles apply to all sizes. If you write the desktop layout first and then try to override for mobile, you end up fighting your own styles.
Too many breakpoints. Most layouts need two or three breakpoints. Using all five on every element creates noise. Start with md (tablet) and lg (desktop); add others only when needed.
Forgetting touch targets on mobile. Buttons and links need at least 44x44px touch targets on mobile. Padding utilities like py-3 px-4 help.
Ignoring landscape orientation. On mobile, landscape mode has a short viewport height. Avoid fixed-height layouts that assume portrait orientation.
Responsive design in Tailwind is about layering breakpoint prefixes onto a solid mobile foundation. Start with the smallest screen, make it look good, then add prefixes to adapt for larger screens. The utility-first approach makes responsive changes explicit and co-located with the elements they affect.
Related articles
- Tailwind Building Custom Components with Tailwind
Extract reusable components from Tailwind utility classes: @apply, component extraction patterns, the plugin API, design tokens, and strategies for maintaining consistency at scale.
- Tailwind Tailwind Responsive Design Patterns
Build mobile-first responsive layouts with Tailwind using breakpoint prefixes, container queries, and grid utilities for real-world UIs.
- Tailwind Tailwind Dark Mode: class Strategy Done Right
Set up dark mode in Tailwind with the class strategy, persist the choice in localStorage, and avoid the flash of wrong theme on first paint.
- Tailwind Tailwind Design Tokens and Theming
Design tokens give your Tailwind project a single source of truth. Learn how to model colors, spacing, and typography for multiple brands and themes.