LearnAI ToolsCareerPractice BuildsPlayContact
Lesson 1617 min read

Dark Mode

Learn how to implement dark mode in Tailwind CSS with the dark: variant, and understand class-based versus media-based dark mode strategies.

Introduction

Dark mode has become a standard expectation for modern web applications, both for aesthetics and to reduce eye strain in low-light environments. Tailwind CSS makes dark mode straightforward with the dark: variant, which applies a utility class only when dark mode is active.

What You Will Learn
  • How the dark: variant works.
  • The difference between media-based and class-based dark mode.
  • How to build a manual light/dark theme toggle.
  • How to choose the right strategy for your project.

The dark: Variant

Prefix any utility with dark: to apply it only in dark mode. It is most commonly used for background colors, text colors, and border colors, letting a single element look correct in both light and dark themes.

A card styled for both themes
<div class="bg-white text-slate-900 dark:bg-slate-900 dark:text-white p-6 rounded-lg">
This card adapts its colors based on the active theme.
</div>
Result

Click Run to see what this code prints.

Media Strategy

By default, Tailwind uses the media strategy, which relies on the prefers-color-scheme CSS media feature. This means dark: styles automatically activate whenever the user's operating system is set to dark mode, with no JavaScript required. It is simple to set up, but the user cannot override it independently of their OS setting.

Media strategy configuration
// tailwind.config.js
module.exports = {
darkMode: 'media', // default behavior
// ...
};

Class Strategy

Setting darkMode to 'class' switches Tailwind to look for a dark class on a parent element (usually <html>) instead of the OS setting. This lets you build a manual toggle button that lets users choose light or dark mode themselves, independent of their system preference.

Class strategy configuration
// tailwind.config.js
module.exports = {
darkMode: 'class',
// ...
};
Applying the dark class manually
<html class="dark">
<body class="bg-white dark:bg-slate-900">
<!-- dark: utilities now apply because the html tag has the dark class -->
</body>
</html>

Building a Theme Toggle

With the class strategy, a theme toggle simply adds or removes the dark class on the document element, typically saving the user's choice to localStorage so it persists across visits.

Simple theme toggle logic
function toggleTheme() {
const html = document.documentElement;
const isDark = html.classList.toggle('dark');
localStorage.setItem('theme', isDark ? 'dark' : 'light');
}
// On page load, restore the saved preference
if (localStorage.getItem('theme') === 'dark') {
document.documentElement.classList.add('dark');
}
Result

Click Run to see what this code prints.

Choosing a Strategy

StrategyBest For
mediaSimple sites that only need to follow the OS setting
classApps that need a user-facing light/dark toggle

Common Mistakes

Avoid These Mistakes
  • Forgetting to set darkMode: 'class' in tailwind.config.js before building a manual toggle — without it, dark: still only follows the OS setting.
  • Only adding dark: styles to backgrounds and forgetting text, border, and shadow colors, which can leave low-contrast or invisible content.
  • Not persisting the user's theme choice, forcing them to re-select it on every visit.
  • Applying the dark class after the page has already rendered, causing a visible flash of the wrong theme.
  • Hardcoding colors with arbitrary hex values instead of Tailwind's color scale, making dark: overrides inconsistent.

Best Practices

  • Use the class strategy whenever you want to offer users a manual toggle.
  • Apply the saved theme class before the page paints (in an inline script) to avoid a flash of incorrect theme.
  • Check contrast carefully in dark mode — colors that work on white backgrounds can be hard to read on dark ones.
  • Test every component in both themes, not just the overall page background.
  • Keep a consistent light/dark color pairing convention across the whole app, such as always pairing slate-900 with white.

Frequently Asked Questions

You configure one strategy globally in tailwind.config.js, but many apps use the class strategy and default the initial class based on prefers-color-scheme, effectively getting the best of both.

The media strategy requires no JavaScript at all. The class strategy needs a small amount of JavaScript to toggle the class and persist the preference.

Yes, variants can be stacked, for example dark:hover:bg-slate-700, which only applies on hover while dark mode is active.

Key Takeaways

  • The dark: variant applies a utility only when dark mode is active.
  • The media strategy follows the operating system's color scheme automatically.
  • The class strategy lets you build a manual light/dark toggle by adding or removing a class on <html>.
  • Persist the user's theme choice in localStorage for a consistent experience.
  • Apply dark: styles to text, borders, and shadows, not just backgrounds.

Summary

Dark mode support in Tailwind is just another variant, no different in spirit from hover: or md:, which makes it easy to weave into components as you build them rather than bolting it on afterward. Next, you will learn how to control borders and rounded corners to give your components clean, polished edges.

Next Lesson →

Borders & Rounded Corners