Skip to content
Back to Design Hub

Responsive Design System with Tailwind

Breakpoint strategy, fluid spacing, and container patterns for Tailwind-based design systems.

Responsive DesignIntermediate

Why

Device fragmentation means a single layout breaks across 360px phones, 768px tablets, and 1440px desktops. Tailwind's utility-first approach with configured breakpoints lets you express responsive intent inline without media query spaghetti or duplicated component variants.

StatCounter 2024 data shows 58% of web traffic is mobile. CSS container queries (baseline 2023) and subgrid (baseline 2024) eliminate most media-query hacks, reducing responsive CSS by 30-50%.

When

Use this approach for marketing sites, dashboards, and apps with 3+ breakpoints. Skip for truly mobile-only or desktop-only apps where responsive logic adds noise without benefit.

How

1. Configure breakpoints — tailwind.config.js screens: { sm: 640, md: 768, lg: 1024, xl: 1280 } 2. Mobile-first — write base styles for smallest, prefix with sm: md: lg: for larger 3. Fluid spacing — use clamp() via theme.extend.spacing: { fluid: 'clamp(1rem, 2vw, 2rem)' } 4. Container query — @tailwindcss/container-queries for component-level responsiveness 5. Grid layouts — grid-cols-1 md:grid-cols-2 lg:grid-cols-3, avoid fixed widths 6. Typography — text-base md:text-lg lg:text-xl, use prose from @tailwindcss/typography 7. Test — Playwright with viewport presets for 360, 768, 1024, 1440 in CI

Example

// tailwind.config.js export default { content: ["./src/**/*.{astro,tsx,html}"], screens: { sm: "640px", md: "768px", lg: "1024px", xl: "1280px" }, theme: { extend: { spacing: { fluid: "clamp(1rem, 2vw, 2rem)" }, fontSize: { fluid: "clamp(1rem, 1.25vw + 0.5rem, 1.5rem)" }, }, }, plugins: [require("@tailwindcss/container-queries")], }; <!-- Card grid — mobile 1 col, tablet 2, desktop 3 --> <div class="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3 sm:gap-6 lg:gap-8"> {items.map((item) => <Card item={item} />)} </div> <!-- Container query — card adapts to its own width, not viewport --> <div class="@container"> <article class="@sm:flex-row flex flex-col gap-4"> <img class="@sm:w-48 w-full rounded-lg" src={item.img} /> <div class="flex-1"> <h3 class="text-fluid font-bold">{item.title}</h3> <p class="mt-2 text-sm text-slate-600">{item.desc}</p> </div> </article> </div>

Common Problems

  • ⚠Breakpoint soup — md:flex-row lg:flex-col xl:flex-row with no documented rationale, impossible to maintain
  • ⚠Fixed pixel widths — w-96 (384px) overflows on 360px phones, use w-full max-w-md instead
  • ⚠Testing only desktop — devs never resize, mobile bugs ship to production
  • ⚠Container queries ignored — components still break when placed in a narrow sidebar vs wide main

Best Practices

  • ✓Document breakpoint intent — comment why md:grid-cols-2 (tablet landscape fits 2 cards comfortably)
  • ✓Use clamp() for fluid values — one rule covers all viewports instead of 4 media queries
  • ✓Prefer container queries for reusable components — they adapt to placement, not viewport
  • ✓Add Playwright visual regression at 4 viewports in CI — catch responsive breaks before merge

FAQ

Why mobile-first — shouldn't I design for desktop?

Mobile-first means base styles target the smallest screen and sm:/md: prefix adds larger. It forces you to fit content in 360px first, avoiding desktop-only assumptions that break on phones.

When should I use container queries instead of media queries?

For reusable components placed in different-width containers (sidebar vs main). Container queries adapt to the component's own width, not the viewport, so the same card works anywhere.

How do I avoid 'breakpoint soup' with md:flex-row lg:flex-col?

Document the intent in a comment for every responsive class, and limit to 3 breakpoints. If a component needs 4+ overrides, redesign the layout — it's too fragile.

Should I use clamp() or media queries for fluid spacing?

clamp() — one rule covers all viewports (clamp(1rem, 2vw, 2rem)) instead of 4 media queries. Use it for spacing and font sizes that should scale smoothly.

How do I test responsive layouts in CI?

Add Playwright visual regression at 4 viewports (360, 768, 1024, 1440). Screenshot each and fail on diff — catches responsive breaks before merge.