Responsive Design System with Tailwind
Breakpoint strategy, fluid spacing, and container patterns for Tailwind-based design systems.
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
Example
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.