
Tailwindcss Responsive Darkmode
- 431 installs
- 50 repo stars
- Updated June 18, 2026
- josiahsiegel/claude-plugin-marketplace
tailwindcss-responsive-darkmode is an agent skill that implements Tailwind CSS responsive breakpoints, class-based and media-query dark mode, and design tokens for developers building mobile-first themed UIs.
About
tailwindcss-responsive-darkmode is a Frontend Development skill from josiahsiegel/claude-plugin-marketplace covering Tailwind CSS responsive design and dark mode for 2025–2026 projects. It documents six default viewport breakpoints from sm (640px) through 2xl (1536px) using mobile-first unprefixed utilities, plus seven container-query breakpoints from @xs to @3xl via @tailwindcss/container-queries. Dark mode sections cover prefers-color-scheme media strategy, class-based .dark toggles with localStorage persistence, three-way light/dark/system switches, data-theme attributes, and next-themes integration for Next.js apps. The skill includes FOUC prevention patterns, semantic @theme color tokens in oklch, WCAG 2.2 contrast guidance, and combined sm:dark: responsive-dark variants. Developers reach for it when implementing runtime theme toggles, container-responsive components, or dark-mode color systems in Tailwind v4.
- Breakpoint and container responsive patterns
- Class vs media dark-mode strategies
- Theme token and variant configuration
- Consistent component light/dark variants
- Mobile-first layout recipes
Tailwindcss Responsive Darkmode by the numbers
- 431 all-time installs (skills.sh)
- +8 installs in the week ending Aug 2, 2026 (Skillselion tracking)
- Ranked #650 of 2,245 Frontend Development skills by installs in the Skillselion catalog
- Data as of Aug 3, 2026 (Skillselion catalog sync)
npx skills add https://github.com/josiahsiegel/claude-plugin-marketplace --skill tailwindcss-responsive-darkmodeAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 431 |
|---|---|
| repo stars | ★ 50 |
| Last updated | June 18, 2026 |
| Repository | josiahsiegel/claude-plugin-marketplace ↗ |
How do you implement Tailwind dark mode with a toggle?
Implement responsive breakpoints and dark-mode theming in Tailwind using class or media strategies, design tokens, and consistent component variants.
Who is it for?
Frontend developers building mobile-first Tailwind UIs who need runtime dark-mode toggles, container queries, and WCAG-compliant theme tokens.
Skip if: Projects using CSS-in-JS or component libraries without Tailwind, or backends with no UI theming requirements.
When should I use this skill?
User asks for Tailwind responsive breakpoints, dark mode setup, prefers-color-scheme handling, FOUC prevention, or next-themes integration.
What you get
Responsive Tailwind component classes, dark-mode toggle JavaScript, next-themes provider setup, and @theme semantic color tokens.
- responsive component markup
- dark-mode toggle script
- theme color tokens
By the numbers
- Documents 6 default viewport breakpoints and 7 container-query breakpoints
- Includes 1 advanced reference file: advanced-responsive-patterns.md
Files
Tailwind CSS Responsive Design & Dark Mode (2025/2026)
Responsive Design
Mobile-First Approach (Industry Standard 2025/2026)
Tailwind uses a mobile-first breakpoint system. With over 60% of global web traffic from mobile devices and Google's mobile-first indexing, this approach is essential.
Key Principle: Unprefixed utilities apply to ALL screen sizes. Breakpoint prefixes apply at that size AND ABOVE.
<!-- CORRECT: Mobile-first (progressive enhancement) -->
<div class="text-sm md:text-base lg:text-lg">...</div>
<!-- INCORRECT: Desktop-first thinking -->
<div class="lg:text-lg md:text-base text-sm">...</div>Default Breakpoints
| Prefix | Min Width | Typical Devices | CSS Media Query |
|---|---|---|---|
| (none) | 0px | All mobile phones | All sizes |
sm: | 640px (40rem) | Large phones, small tablets | @media (min-width: 640px) |
md: | 768px (48rem) | Tablets (portrait) | @media (min-width: 768px) |
lg: | 1024px (64rem) | Tablets (landscape), laptops | @media (min-width: 1024px) |
xl: | 1280px (80rem) | Desktops | @media (min-width: 1280px) |
2xl: | 1536px (96rem) | Large desktops | @media (min-width: 1536px) |
2025/2026 Device Coverage
Common device sizes to test:
- 320px: Older iPhones, smallest supported
- 375px: Modern iPhone base (~17% of mobile)
- 390-430px: Modern large phones (~35% of mobile)
- 768px: iPad portrait
- 1024px: iPad landscape, laptops
- 1280px: Standard laptops/desktops
- 1440px: Large desktops
- 1920px: Full HD displays
Custom Breakpoints
@theme {
/* Add custom breakpoints for specific content needs */
--breakpoint-xs: 20rem; /* 320px - very small devices */
--breakpoint-3xl: 100rem; /* 1600px */
--breakpoint-4xl: 120rem; /* 1920px - full HD */
/* Override existing breakpoints based on YOUR content */
--breakpoint-sm: 36rem; /* 576px - when content needs space */
--breakpoint-lg: 62rem; /* 992px - common content width */
}Usage:
<div class="grid xs:grid-cols-2 3xl:grid-cols-6">
<!-- Custom breakpoints work like built-in ones -->
</div>Content-Driven Breakpoints (2025 Best Practice)
Instead of targeting devices, let your content determine breakpoints:
@theme {
/* Based on content needs, not device specs */
--breakpoint-prose: 65ch; /* Optimal reading width */
--breakpoint-content: 75rem; /* Main content max */
}Test your design at various widths and add breakpoints where layout breaks.
Responsive Examples
Responsive Grid
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
<div>Item 1</div>
<div>Item 2</div>
<div>Item 3</div>
<div>Item 4</div>
</div>Responsive Typography
<h1 class="text-2xl sm:text-3xl md:text-4xl lg:text-5xl font-bold">
Responsive Heading
</h1>
<p class="text-sm md:text-base lg:text-lg leading-relaxed">
Responsive paragraph text
</p>Responsive Spacing
<section class="py-8 md:py-12 lg:py-16 px-4 md:px-8 lg:px-12">
<div class="max-w-4xl mx-auto">
Content with responsive padding
</div>
</section>Responsive Navigation
<nav class="flex flex-col md:flex-row items-center justify-between">
<div class="hidden md:flex gap-4">
<!-- Desktop navigation -->
</div>
<button class="md:hidden">
<!-- Mobile menu button -->
</button>
</nav>Show/Hide Based on Screen Size
<!-- Hidden on mobile, visible on desktop -->
<div class="hidden md:block">Desktop only</div>
<!-- Visible on mobile, hidden on desktop -->
<div class="block md:hidden">Mobile only</div>
<!-- Different content per breakpoint -->
<span class="sm:hidden">XS</span>
<span class="hidden sm:inline md:hidden">SM</span>
<span class="hidden md:inline lg:hidden">MD</span>
<span class="hidden lg:inline xl:hidden">LG</span>
<span class="hidden xl:inline 2xl:hidden">XL</span>
<span class="hidden 2xl:inline">2XL</span>Container Queries (v4) - 2025 Game-Changer
Container queries enable component-level responsiveness, independent of viewport size. This is essential for reusable components in 2025.
@plugin "@tailwindcss/container-queries";<!-- Mark parent as a query container -->
<div class="@container">
<div class="flex flex-col @md:flex-row @lg:gap-8">
<!-- Responds to container size, not viewport -->
</div>
</div>
<!-- Named containers for multiple contexts -->
<div class="@container/card">
<div class="@lg/card:grid-cols-2 grid grid-cols-1">
<!-- Responds specifically to 'card' container -->
</div>
</div>Container Query Breakpoints
| Class | Min-width | Use Case |
|---|---|---|
@xs | 20rem (320px) | Small widgets |
@sm | 24rem (384px) | Compact cards |
@md | 28rem (448px) | Standard cards |
@lg | 32rem (512px) | Wide cards |
@xl | 36rem (576px) | Full-width components |
@2xl | 42rem (672px) | Large containers |
@3xl | 48rem (768px) | Page sections |
When to Use Container vs Viewport Queries
| Container Queries | Viewport Queries |
|---|---|
| Reusable components | Page-level layouts |
| Cards in various contexts | Navigation bars |
| Sidebar widgets | Hero sections |
| CMS/embedded content | Full-width sections |
Max-Width Breakpoints
Target screens below a certain size:
<!-- Only on screens smaller than md (< 768px) -->
<div class="md:hidden">Small screens only</div>
<!-- Custom max-width media query -->
<div class="[@media(max-width:600px)]:text-sm">
Custom max-width
</div>Dark Mode
Strategy: Media (Default)
Dark mode follows the user's operating system preference using prefers-color-scheme:
@import "tailwindcss";
/* No additional configuration needed */<div class="bg-white dark:bg-gray-900">
<h1 class="text-gray-900 dark:text-white">Title</h1>
<p class="text-gray-600 dark:text-gray-300">Content</p>
</div>Strategy: Selector (Manual Toggle)
Control dark mode with a CSS class:
@import "tailwindcss";
@custom-variant dark (&:where(.dark, .dark *));<!-- Add .dark class to html or body to enable dark mode -->
<html class="dark">
<body>
<div class="bg-white dark:bg-gray-900">
Content
</div>
</body>
</html>JavaScript Toggle
// Simple toggle
function toggleDarkMode() {
document.documentElement.classList.toggle('dark');
}
// With localStorage persistence
function initDarkMode() {
const isDark = localStorage.getItem('darkMode') === 'true' ||
(!localStorage.getItem('darkMode') &&
window.matchMedia('(prefers-color-scheme: dark)').matches);
document.documentElement.classList.toggle('dark', isDark);
}
function toggleDarkMode() {
const isDark = document.documentElement.classList.toggle('dark');
localStorage.setItem('darkMode', isDark);
}
// Initialize on page load
initDarkMode();Three-Way Toggle (Light/Dark/System)
const themes = ['light', 'dark', 'system'];
function setTheme(theme) {
localStorage.setItem('theme', theme);
applyTheme();
}
function applyTheme() {
const theme = localStorage.getItem('theme') || 'system';
const isDark = theme === 'dark' ||
(theme === 'system' && window.matchMedia('(prefers-color-scheme: dark)').matches);
document.documentElement.classList.toggle('dark', isDark);
}
// Listen for system preference changes
window.matchMedia('(prefers-color-scheme: dark)')
.addEventListener('change', () => {
if (localStorage.getItem('theme') === 'system') {
applyTheme();
}
});
applyTheme();Data Attribute Strategy
@custom-variant dark (&:where([data-theme="dark"], [data-theme="dark"] *));<html data-theme="dark">
<body>
<div class="bg-white dark:bg-gray-900">Content</div>
</body>
</html>Dark Mode with Next.js (next-themes)
npm install next-themes// app/providers.tsx
'use client';
import { ThemeProvider } from 'next-themes';
export function Providers({ children }) {
return (
<ThemeProvider attribute="class" defaultTheme="system">
{children}
</ThemeProvider>
);
}// app/layout.tsx
import { Providers } from './providers';
export default function RootLayout({ children }) {
return (
<html lang="en" suppressHydrationWarning>
<body>
<Providers>{children}</Providers>
</body>
</html>
);
}// components/ThemeToggle.tsx
'use client';
import { useTheme } from 'next-themes';
export function ThemeToggle() {
const { theme, setTheme } = useTheme();
return (
<button onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}>
Toggle Theme
</button>
);
}Dark Mode Color Palette
<!-- Text colors -->
<p class="text-gray-900 dark:text-gray-100">Primary text</p>
<p class="text-gray-600 dark:text-gray-400">Secondary text</p>
<p class="text-gray-400 dark:text-gray-500">Muted text</p>
<!-- Background colors -->
<div class="bg-white dark:bg-gray-900">Page background</div>
<div class="bg-gray-50 dark:bg-gray-800">Card background</div>
<div class="bg-gray-100 dark:bg-gray-700">Elevated background</div>
<!-- Border colors -->
<div class="border border-gray-200 dark:border-gray-700">Bordered element</div>
<!-- Interactive elements -->
<button class="bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-700">
Button
</button>Dark Mode with CSS Variables
@theme {
/* Light mode colors (default) */
--color-bg-primary: oklch(1 0 0);
--color-bg-secondary: oklch(0.98 0 0);
--color-text-primary: oklch(0.15 0 0);
--color-text-secondary: oklch(0.4 0 0);
}
/* Dark mode overrides */
@media (prefers-color-scheme: dark) {
:root {
--color-bg-primary: oklch(0.15 0 0);
--color-bg-secondary: oklch(0.2 0 0);
--color-text-primary: oklch(0.95 0 0);
--color-text-secondary: oklch(0.7 0 0);
}
}<div class="bg-[var(--color-bg-primary)] text-[var(--color-text-primary)]">
Semantic colors
</div>Typography Plugin Dark Mode
<article class="prose dark:prose-invert">
<!-- Markdown content automatically adapts to dark mode -->
</article>Combining Responsive and Dark Mode
<!-- Different layouts AND colors based on screen size and theme -->
<div class="
grid grid-cols-1 md:grid-cols-2
bg-white dark:bg-gray-900
p-4 md:p-8
text-gray-900 dark:text-white
">
<div class="hidden dark:md:block">
Only visible on md+ screens in dark mode
</div>
</div>Best Practices (2025/2026)
1. Start Mobile, Then Enhance
<!-- CORRECT: Mobile-first progression -->
<div class="text-sm md:text-base lg:text-lg">
<!-- WRONG: Desktop-first thinking (more code, more bugs) -->
<div class="lg:text-lg md:text-base text-sm">2. Touch-Friendly Interactive Elements
WCAG 2.2 requires 24x24px minimum, but 44x44px is recommended:
<!-- Touch-friendly button (44px minimum) -->
<button class="min-h-11 min-w-11 px-4 py-2.5">
Click me
</button>
<!-- Touch-friendly navigation link -->
<a href="#" class="block py-3 px-4 min-h-11">
Navigation Item
</a>
<!-- Adequate spacing between touch targets -->
<div class="flex gap-3">
<button class="min-h-11 px-4 py-2">Button 1</button>
<button class="min-h-11 px-4 py-2">Button 2</button>
</div>3. Fluid Typography (Eliminates Breakpoint Jumps)
@theme {
--text-fluid-base: clamp(1rem, 0.9rem + 0.5vw, 1.25rem);
--text-fluid-lg: clamp(1.25rem, 1rem + 1.25vw, 2rem);
--text-fluid-xl: clamp(1.5rem, 1rem + 2.5vw, 3rem);
}<h1 class="text-fluid-xl font-bold">Smoothly Scaling Heading</h1>
<p class="text-fluid-base leading-relaxed">Smoothly scaling body text.</p>2. Use Semantic Dark Mode Colors
@theme {
/* Instead of raw colors, use semantic names */
--color-surface: oklch(1 0 0);
--color-surface-dark: oklch(0.15 0 0);
--color-on-surface: oklch(0.1 0 0);
--color-on-surface-dark: oklch(0.95 0 0);
}3. Test All Breakpoints
Use the debug-screens plugin during development:
npm install -D @tailwindcss/debug-screens@plugin "@tailwindcss/debug-screens";4. Reduce Repetition with Components
/* components.css */
@layer components {
.card {
@apply bg-white dark:bg-gray-800 rounded-lg p-6 shadow-sm;
}
.section {
@apply py-12 md:py-16 lg:py-24;
}
}5. Consider Color Contrast
Ensure sufficient contrast in both light and dark modes (WCAG 2.2):
- Normal text: 4.5:1 contrast ratio minimum
- Large text (18pt+): 3:1 contrast ratio minimum
- Interactive elements: 3:1 against adjacent colors
<!-- Good contrast in both modes -->
<button class="
bg-blue-600 text-white
dark:bg-blue-500 dark:text-white
hover:bg-blue-700 dark:hover:bg-blue-400
/* Focus ring for accessibility */
focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2
">
Action
</button>6. Reduced Motion Preference
Respect users who prefer reduced motion:
<div class="
transition-transform duration-300
hover:scale-105
motion-reduce:transition-none
motion-reduce:hover:scale-100
">
Respects motion preferences
</div>7. Performance-Optimized Responsive Images
<!-- Lazy load below-fold images -->
<img
src="image.jpg"
alt="Description"
loading="lazy"
class="w-full h-auto"
/>
<!-- Responsive srcset -->
<img
src="medium.jpg"
srcset="small.jpg 400w, medium.jpg 800w, large.jpg 1200w"
sizes="(min-width: 1024px) 50vw, 100vw"
alt="Responsive image"
loading="lazy"
class="w-full h-auto"
/>8. Safe Area Handling (Notched Devices)
@utility safe-area-pb {
padding-bottom: env(safe-area-inset-bottom);
}<!-- Bottom navigation respects device notch -->
<nav class="fixed bottom-0 inset-x-0 safe-area-pb bg-white border-t">
Navigation
</nav>Advanced Responsive Patterns (2025/2026)
Container Queries - The 2025 Game-Changer
Container queries allow components to respond to their parent container's size rather than the viewport. This is essential for reusable component design in modern applications.
Setup
@import "tailwindcss";
@plugin "@tailwindcss/container-queries";Basic Container Query
<div class="@container">
<article class="flex flex-col @md:flex-row @md:items-center gap-4">
<img class="w-full @md:w-48 aspect-video object-cover rounded-lg" />
<div>
<h3 class="text-lg @lg:text-xl font-semibold">Title</h3>
<p class="text-sm @md:text-base text-gray-600">Description</p>
</div>
</article>
</div>Named Containers
<div class="@container/sidebar">
<nav class="@lg/sidebar:flex-row flex flex-col">
<!-- Responds to sidebar container width -->
</nav>
</div>
<div class="@container/main">
<section class="@xl/main:grid-cols-3 grid grid-cols-1">
<!-- Responds to main container width -->
</section>
</div>Container Query Breakpoints
| Class | Min-width |
|---|---|
@xs | 20rem (320px) |
@sm | 24rem (384px) |
@md | 28rem (448px) |
@lg | 32rem (512px) |
@xl | 36rem (576px) |
@2xl | 42rem (672px) |
@3xl | 48rem (768px) |
Custom Container Breakpoints
@theme {
--container-3xs: 16rem;
--container-2xs: 18rem;
--container-4xl: 56rem;
}Advanced Breakpoint Patterns
Between Breakpoints
<!-- Only between sm and md -->
<div class="hidden sm:block md:hidden">
Tablet only content
</div>
<!-- Only on large screens (not xl+) -->
<div class="hidden lg:flex xl:hidden">
Large but not extra-large
</div>Max-Width Breakpoints
/* Custom max-width variant */
@custom-variant max-sm (media(width < 640px));
@custom-variant max-md (media(width < 768px));
@custom-variant max-lg (media(width < 1024px));<div class="max-md:flex-col flex flex-row">
Column on mobile, row on tablet+
</div>Orientation Variants
<div class="portrait:flex-col landscape:flex-row flex">
Adapts to device orientation
</div>Print Styles
<div class="print:hidden">
Hidden when printing
</div>
<div class="hidden print:block">
Only visible when printing
</div>
<nav class="bg-blue-600 print:bg-transparent print:text-black">
Printer-friendly navigation
</nav>Fluid Typography
Using clamp()
@theme {
--text-fluid-sm: clamp(0.875rem, 0.8rem + 0.25vw, 1rem);
--text-fluid-base: clamp(1rem, 0.9rem + 0.5vw, 1.25rem);
--text-fluid-lg: clamp(1.25rem, 1rem + 1vw, 1.75rem);
--text-fluid-xl: clamp(1.5rem, 1rem + 2vw, 2.5rem);
--text-fluid-2xl: clamp(2rem, 1rem + 3vw, 4rem);
}<h1 class="text-fluid-2xl font-bold">Responsive Heading</h1>
<p class="text-fluid-base">Paragraph that scales smoothly</p>Fluid Spacing
@theme {
--spacing-fluid-sm: clamp(0.5rem, 0.25rem + 1vw, 1rem);
--spacing-fluid-md: clamp(1rem, 0.5rem + 2vw, 2rem);
--spacing-fluid-lg: clamp(2rem, 1rem + 3vw, 4rem);
}<section class="py-fluid-lg px-fluid-md">
Fluid padding that scales with viewport
</section>Responsive Grid Systems
Auto-Fit Grid
<!-- Cards auto-fit with minimum 280px -->
<div class="grid grid-cols-[repeat(auto-fit,minmax(280px,1fr))] gap-6">
<Card />
<Card />
<Card />
</div>Responsive Sidebar Layout
<div class="grid grid-cols-1 lg:grid-cols-[280px_1fr] gap-6">
<aside class="hidden lg:block">Sidebar</aside>
<main>Content</main>
</div>
<!-- With collapsible sidebar -->
<div class="grid grid-cols-1 lg:grid-cols-[auto_1fr] gap-6">
<aside class="w-16 lg:w-64 transition-all duration-300">
<span class="hidden lg:inline">Full text</span>
<span class="lg:hidden">Icon</span>
</aside>
<main>Content</main>
</div>Holy Grail Layout
<div class="min-h-screen grid grid-rows-[auto_1fr_auto]">
<header class="h-16 bg-white border-b">Header</header>
<div class="grid grid-cols-1 md:grid-cols-[200px_1fr] lg:grid-cols-[200px_1fr_200px]">
<nav class="hidden md:block bg-gray-50 p-4">Navigation</nav>
<main class="p-6">Main Content</main>
<aside class="hidden lg:block bg-gray-50 p-4">Sidebar</aside>
</div>
<footer class="h-16 bg-gray-900 text-white">Footer</footer>
</div>Responsive Component Patterns
Responsive Navigation
<nav class="flex items-center justify-between p-4">
<Logo />
<!-- Desktop nav -->
<ul class="hidden md:flex items-center gap-6">
<li><a href="#">Home</a></li>
<li><a href="#">About</a></li>
<li><a href="#">Services</a></li>
<li><a href="#">Contact</a></li>
</ul>
<!-- Mobile menu button -->
<button class="md:hidden p-2">
<MenuIcon />
</button>
</nav>
<!-- Mobile nav (shown when open) -->
<div class="md:hidden fixed inset-0 bg-white z-50">
<ul class="flex flex-col p-4 gap-4">
<li><a href="#">Home</a></li>
<li><a href="#">About</a></li>
<li><a href="#">Services</a></li>
<li><a href="#">Contact</a></li>
</ul>
</div>Responsive Table
<!-- Stack on mobile, table on desktop -->
<div class="overflow-x-auto">
<table class="w-full">
<thead class="hidden md:table-header-group">
<tr class="border-b">
<th class="text-left p-3">Name</th>
<th class="text-left p-3">Email</th>
<th class="text-left p-3">Role</th>
<th class="text-left p-3">Actions</th>
</tr>
</thead>
<tbody>
<tr class="flex flex-col md:table-row border-b py-4 md:py-0">
<td class="p-3" data-label="Name">
<span class="md:hidden font-medium">Name: </span>
John Doe
</td>
<td class="p-3" data-label="Email">
<span class="md:hidden font-medium">Email: </span>
john@example.com
</td>
<td class="p-3" data-label="Role">
<span class="md:hidden font-medium">Role: </span>
Admin
</td>
<td class="p-3">
<Button size="sm">Edit</Button>
</td>
</tr>
</tbody>
</table>
</div>Responsive Cards
<!-- Card that changes layout at container breakpoint -->
<div class="@container">
<article class="
flex flex-col @sm:flex-row
gap-4 p-4
bg-white rounded-xl shadow-sm
">
<img
src="..."
class="
w-full @sm:w-32 @md:w-48
aspect-video @sm:aspect-square
object-cover rounded-lg
"
/>
<div class="flex-1">
<h3 class="text-lg @md:text-xl font-semibold">Card Title</h3>
<p class="text-gray-600 mt-2 line-clamp-2 @md:line-clamp-3">
Description text that adapts to available space...
</p>
<div class="mt-4 flex flex-wrap gap-2">
<Badge>Tag 1</Badge>
<Badge>Tag 2</Badge>
</div>
</div>
</article>
</div>Motion and Accessibility
Reduced Motion
<div class="
transition-transform duration-300
motion-safe:hover:scale-105
motion-reduce:transition-none
">
Respects motion preferences
</div>Forced Colors Mode
<button class="
bg-blue-600 text-white
forced-colors:border-2 forced-colors:border-current
">
Works in high contrast mode
</button>Safe Area Handling (Notched Devices)
For devices with notches (iPhone X+, modern Android), respect safe areas:
Custom Safe Area Utilities
@utility safe-area-pt {
padding-top: env(safe-area-inset-top);
}
@utility safe-area-pb {
padding-bottom: env(safe-area-inset-bottom);
}
@utility safe-area-pl {
padding-left: env(safe-area-inset-left);
}
@utility safe-area-pr {
padding-right: env(safe-area-inset-right);
}
@utility safe-area-p {
padding: env(safe-area-inset-top) env(safe-area-inset-right)
env(safe-area-inset-bottom) env(safe-area-inset-left);
}Usage
<!-- Header respects top notch -->
<header class="sticky top-0 safe-area-pt bg-white border-b">
<nav class="h-14 flex items-center px-4">Navigation</nav>
</header>
<!-- Bottom navigation respects home indicator -->
<nav class="fixed bottom-0 inset-x-0 safe-area-pb bg-white border-t">
<div class="flex justify-around py-2">Bottom nav</div>
</nav>
<!-- Full-screen app shell -->
<div class="min-h-screen safe-area-p">
App content
</div>Performance Optimizations for Responsive Design
Content Visibility for Off-Screen Content
@utility content-auto {
content-visibility: auto;
contain-intrinsic-size: auto 500px;
}<section class="content-auto">
<!-- Content below fold - rendering deferred until needed -->
Large section content
</section>Lazy Loading
<!-- Native lazy loading for images -->
<img
src="image.jpg"
alt="Description"
loading="lazy"
decoding="async"
class="w-full h-auto"
/>
<!-- Lazy load iframes -->
<iframe
src="embed.html"
loading="lazy"
class="w-full aspect-video"
></iframe>Reduced Data Mode
@custom-variant prefers-reduced-data (media(prefers-reduced-data: reduce));<!-- Show simpler content on slow/metered connections -->
<div class="block prefers-reduced-data:hidden">
<video autoplay muted loop>Full video</video>
</div>
<div class="hidden prefers-reduced-data:block">
<img src="poster.jpg" alt="Video poster" />
</div>2025/2026 CSS Features
View Transitions (Progressive Enhancement)
@utility view-transition-name-* {
view-transition-name: --value(ident);
}<div class="view-transition-name-card">
Animates during page transitions
</div>Subgrid for Aligned Nested Grids
<div class="grid grid-cols-3 gap-4">
<div class="col-span-2 grid grid-cols-subgrid">
<!-- Child grid aligns with parent columns -->
<div>Aligned 1</div>
<div>Aligned 2</div>
</div>
</div>:has() Selector for Parent Selection
/* Style parent based on child state */
.card:has(input:focus) {
@apply ring-2 ring-blue-500;
}
/* Show sibling when checkbox checked */
.toggle:has(input:checked) + .content {
@apply block;
}Best Practices Summary
| Pattern | Implementation | Use Case |
|---|---|---|
| Viewport queries | md:, lg: prefixes | Page layouts |
| Container queries | @md:, @lg: prefixes | Reusable components |
| Fluid typography | clamp() in @theme | Smooth scaling |
| Touch targets | min-h-11 min-w-11 | Mobile interactions |
| Safe areas | env(safe-area-inset-*) | Notched devices |
| Reduced motion | motion-reduce: prefix | Accessibility |
| Lazy loading | loading="lazy" | Performance |
| Content visibility | content-visibility: auto | Render optimization |
Related skills
How it compares
Pick tailwindcss-responsive-darkmode over generic CSS skills when the stack is Tailwind v4 and you need both responsive layout and dark-mode toggle patterns together.
FAQ
How does tailwindcss-responsive-darkmode prevent dark mode FOUC?
tailwindcss-responsive-darkmode recommends initializing theme from localStorage or prefers-color-scheme before paint, toggling html.dark or data-theme early, and using next-themes with suppressHydrationWarning in Next.js layouts to avoid flash of wrong theme on load.
What breakpoints does tailwindcss-responsive-darkmode document?
tailwindcss-responsive-darkmode documents six default min-width breakpoints—sm 640px, md 768px, lg 1024px, xl 1280px, and 2xl 1536px—plus seven container-query breakpoints from @xs 320px through @3xl 768px for component-level responsiveness.