Dark Mode & Theming
Tailwind makes dark mode and theming straightforward with the dark: variant and CSS variables.
The dark: Variant
Add dark-specific styles alongside the light ones:
<div class="bg-white text-gray-900 dark:bg-gray-900 dark:text-gray-100">
<h1 class="text-gray-900 dark:text-white">Title</h1>
<p class="text-gray-600 dark:text-gray-400">Body</p>
</div>
Every color utility has a dark counterpart. Pair them as you write.
Choosing the Dark Mode Strategy
Two common approaches:
- Media — Follow the operating system setting automatically.
- Class/selector — Toggle a class on
<html>so users can choose.
Configure it in your CSS:
@custom-variant dark (&:where(.dark, .dark *));
Then toggling class="dark" on <html> switches the theme.
Toggling in JavaScript
const root = document.documentElement;
const stored = localStorage.getItem("theme");
if (stored === "dark" || (!stored && matchMedia("(prefers-color-scheme: dark)").matches)) {
root.classList.add("dark");
}
function toggleTheme() {
root.classList.toggle("dark");
localStorage.setItem("theme", root.classList.contains("dark") ? "dark" : "light");
}
Persist the choice so it survives reloads.
Design Tokens with CSS Variables
Define semantic colors once, then reference them:
@import "tailwindcss";
@theme {
--color-background: oklch(1 0 0);
--color-foreground: oklch(0.2 0 0);
}
.dark {
--color-background: oklch(0.15 0 0);
--color-foreground: oklch(0.95 0 0);
}
Now bg-background and text-foreground automatically flip with the theme. Semantic names beat hardcoded gray-900 scattered everywhere.
Best Practices
- Use semantic tokens —
bg-background, notbg-gray-100. - Check contrast in both themes — Dark mode is not just inverted colors.
- Respect system preference by default.
- Persist the user’s choice.
Common Mistakes
- Only styling light mode — Dark users get white flashes.
- Hardcoding colors everywhere — Theming becomes a find-and-replace.
- Forgetting images and shadows — They often need dark adjustments.
- Low contrast — Pure black on pure white is harsh; use near-black/near-white.