How to Set Up Dark Mode with TailwindCSS 4
A quick guide to understand how to handle Dark Mode in Tailwindcss 4

CTO of Allocations.com, a finance SaaS Miami-based, I am running a YouTube channel: @codewithguillaume. With 15 years of exp. as a freelancer, consultant, and Lead Developer, I have led dozens of engineering teams across Paris, London, and Berlin. I am father of 2 and I live in Dubai.
TailwindCSS 4 introduced a major shift in how themes, tokens, and variants work.
And one of the biggest changes: dark mode no longer works out of the box.
If you upgraded from Tailwind 3 to 4, you probably noticed this instantly:
dark:bg-blackdoes nothingadding
.darkon<html>has no effectdark:classes simply don’t get generated
Why?
Because TailwindCSS v4 removed the old darkMode: 'class' configuration and the internal dark variant.
But the good news is:
➡️ Dark mode is still fully supported
➡️ You just need to enable it explicitly
➡️ The new setup is actually more powerful
In this guide, I’ll show you exactly how to set up dark mode in TailwindCSS 4, step-by-step.
1. The Key Change in TailwindCSS 4
In TailwindCSS v3 and below, dark mode was enabled via:
module.exports = {
darkMode: "class",
};
In TailwindCSS v4, the entire config file is gone, and so is that option.
Variants (like dark:) now must be declared manually using the new @custom-variant rule.
This is the heart of the solution.
2. Create Your Dark Variant
In your global CSS file (usually src/styles/global.css or app.css):
@import "tailwindcss";
/* Declare the dark variant */
@custom-variant dark (&:where(.dark, .dark *));
This line simply tells Tailwind:
Generate
dark:classes that apply whenever an element is inside.dark.
This is equivalent to Tailwind v3’s .dark strategy.
3. Enable Native Browser Color Scheme
Still in your CSS:
:root {
color-scheme: light;
}
.dark {
color-scheme: dark;
}
This ensures built-in elements (inputs, scrollbars, form elements) also switch to dark mode.
4. Add Dark Styles
Now you can write Tailwind like before:
@layer base {
html {
@apply bg-white text-black dark:bg-neutral-950 dark:text-neutral-100;
}
p {
@apply text-neutral-600 dark:text-neutral-400;
}
}
Yes — dark: works exactly as in Tailwind 3.
5. Add Your Theme Tokens (Optional)
TailwindCSS 4 introduces a powerful @theme rule:
@theme {
--color-primary-500: #00e983;
--color-primary-700: #00c269;
--font-sans: "Geist", sans-serif;
}
Your theme tokens are now auto-generated as utilities:
text-primary-500bg-primary-500font-sans
6. Toggle Dark Mode with JavaScript
Tailwind 4 does not change how you toggle dark mode.
Just add/remove .dark on <html>:
document.documentElement.classList.toggle("dark");
Or save it in localStorage:
const toggle = () => {
const html = document.documentElement;
const dark = html.classList.toggle("dark");
localStorage.setItem("dark-mode", dark);
};
if (localStorage.getItem("dark-mode") === "true") {
document.documentElement.classList.add("dark");
}
7. Example: Complete Working Setup
Here is a minimal working example:
global.css
@import "tailwindcss";
/* Enable the dark: variant */
@custom-variant dark (&:where(.dark, .dark *));
:root {
color-scheme: light;
}
.dark {
color-scheme: dark;
}
@layer base {
html {
@apply bg-white text-black dark:bg-neutral-950 dark:text-neutral-100;
}
}
HTML / Astro / React
<button onclick="document.documentElement.classList.toggle('dark')">
Toggle
</button>
<div class="p-4 bg-white dark:bg-red-500">
Dark mode test
</div>
When you click the button, the card turns red in dark mode.
8. Common Pitfalls (and Fixes)
❌ 1. Forgetting to add @custom-variant
Dark mode will never work without:
@custom-variant dark (&:where(.dark, .dark *));
❌ 2. Putting @theme inside @layer
It must be at top level.
❌ 3. Your framework overwrites <html class="dark">
Astro layouts often do this accidentally.
❌ 4. Missing CSS import
Make sure your global CSS is loaded.
9. Why Tailwind 4 Changed This
TailwindCSS 4 is designed around:
Native CSS
Zero JS config
Custom tokens
Full CSS power with Tailwind utilities
Fine-grained variant control
Smaller CSS output
By moving variants to CSS, Tailwind becomes:
More flexible
Easier to customize
Better for future tooling
Less magic, more explicit control
Conclusion
TailwindCSS 4’s dark mode setup is different, but once you understand it, it’s actually cleaner and more powerful than before.
To summarize:
✅ 1. Import Tailwind
✅ 2. Declare the dark variant
@custom-variant dark (&:where(.dark, .dark *));
✅ 3. Add color-scheme
✅ 4. Add dark:* classes
✅ 5. Toggle .dark with JavaScript
Once you do these steps, dark mode works exactly as expected.


