Choosing Tailwind CSS Dark Mode: Media vs Class Strategy
Tailwind dark mode forces a choice: media query or class toggle. This guide compares both strategies, their trade-offs, and a concrete class-based implementation with flash prevention.
02 Jun 2026, 01:00 UTC

Decision Guide: Tailwind Dark Mode – Media or Class?
When you add dark mode to a Tailwind-based project you face one critical decision: use the prefers-color-scheme media query (the media strategy) or toggle a dark class on the root element (the class strategy). Both are fully supported in Tailwind CSS v2.1 and later via the darkMode config option, but they differ in user control, server-side rendering (SSR) behavior, and how much JavaScript you need.
What the Decision Affects
- Automatic adaptation – does the theme follow the OS setting on its own?
- User override – can a visitor toggle the theme without a page reload?
- SSR consistency – does the server-rendered markup already match the final theme?
- Flash of incorrect theme – does the page briefly show the wrong colors on load?
- Preference persistence – can you store and restore the user's choice?
Option Comparison
| Feature | Media Strategy | Class Strategy |
|---|---|---|
| Automatic OS sync | Yes – browser applies @media (prefers-color-scheme: dark) | No – you must read the setting yourself |
| User toggle without reload | No – the media query cannot be changed by page JS | Yes – add/remove the dark class |
| SSR consistency | Often mismatched – server renders light, client switches after hydration | Yes – render the dark class server-side when needed |
| Flash of wrong theme | Possible during hydration | Preventable with an early inline script |
| JavaScript required | None | Small script to manage the class |
| Preference persistence | Not built in | Easy via localStorage |
When to Pick Media
Choose the media strategy for static sites, documentation, or content pages where you want zero client-side JavaScript and are happy for the OS setting to be the single source of truth. The trade-off: no in-page toggle, and SSR pages can flash the wrong theme because the server doesn't know the client's OS preference.
When to Pick Class
Choose the class strategy for applications that need a toggle button, persisted user preference, or SSR frameworks like Next.js, Nuxt, or Remix. It works with every Tailwind build mode (JIT or traditional) and eliminates hydration mismatch — at the cost of a small script that must run before styles apply.
Concrete Implementation – Class Strategy
1. Tailwind config
// tailwind.config.js
module.exports = {
darkMode: 'class',
content: ['./src/**/*.{html,js,jsx,ts,tsx}'],
theme: { extend: {} },
plugins: [],
}2. Set the class before first paint
Run this inline in the <head>, before the stylesheet loads, so the correct class exists before any rendering. Run it in the browser; no special permissions needed.
<script>
(function () {
var stored = localStorage.getItem('theme');
var prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
if (stored === 'dark' || (!stored && prefersDark)) {
document.documentElement.classList.add('dark');
}
})();
</script>Risk: if this script loads after your CSS or is deferred, users may see a flash of the wrong theme. Keep it synchronous and inline.
3. Toggle button
function toggleDark() {
var isDark = document.documentElement.classList.toggle('dark');
localStorage.setItem('theme', isDark ? 'dark' : 'light');
}
document.getElementById('darkToggle').addEventListener('click', toggleDark);4. Use dark variants in markup
<div class="bg-white dark:bg-gray-800 text-black dark:text-white p-4">
Hello World
</div>Verification Checklist
- Render check – open the page and inspect
<html>; it should carry thedarkclass when the stored or system preference is dark. - Toggle test – click the toggle and confirm the class flips and colors update without a reload.
- CSS check – run your production build (e.g.,
npm run build) and confirm the output CSS scopes dark variants under a.darkselector rather than a media query. - Flash test – hard-reload with dark enabled and watch for a light flash; if seen, move the init script earlier in
<head>.
Limitations and Caveats
- Do not mix strategies: Tailwind respects only one
darkModesetting, so combining media and class approaches produces inconsistent results. - With the media strategy there is no supported way to offer a user toggle without a reload.
- Older browsers without
prefers-color-schemesupport simply never get dark mode under the media strategy; the class strategy works everywhere.
Practical Takeaway
For most modern apps that need a user toggle and SSR-friendly rendering, pick darkMode: 'class' with an early inline init script. Use the media strategy only when you want zero JavaScript and the OS setting alone is acceptable.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.