Tailwind CSS Dark Mode — dark: Variant and Strategy Configuration
In this tutorial, you will learn about Tailwind CSS Dark Mode. We cover key concepts, practical examples, and best practices to help you master this topic.
Tailwind CSS dark mode provides a dark: prefix that applies styles when dark mode is active, supporting both system preference (media Strategy) and manual toggle (class strategy).
What You'll Learn
You will learn how to enable dark mode in the config, use the dark: variant with any utility, configure class strategy for manual toggling, and build dark mode compatible components.
Why It Matters
Dark mode reduces eye strain and saves battery on OLED screens. DodaTech's tools including Doda Browser and Durga Antivirus Pro all support dark mode using Tailwind's dark: variant.
Real-World Use
Durga Antivirus Pro's dashboard uses dark:bg-gray-900 for the background, dark:text-white for text, and dark:border-gray-700 for borders, providing a complete dark theme with minimal code.
flowchart LR
A[States] --> B[Dark Mode]
B --> C[media Strategy]
B --> D[class Strategy]
B --> E[dark: Variant]
B --> F[Toggle]
style B fill:#38bdf8,stroke:#0284c7,color:#fff
style C fill:#22c55e,stroke:#16a34a,color:#fff
Media Strategy (System Preference)
// tailwind.config.js - dark mode by system preference
module.exports = {
darkMode: 'media',
// ...
}
<div class="bg-white dark:bg-gray-900 min-h-screen p-8">
<div class="max-w-md mx-auto bg-gray-50 dark:bg-gray-800 rounded-xl p-6 shadow-lg">
<h2 class="text-gray-900 dark:text-white text-xl font-bold">
System Dark Mode
</h2>
<p class="text-gray-600 dark:text-gray-300 mt-2">
This card follows the system dark mode setting. Try toggling your OS theme.
</p>
<div class="mt-4 flex gap-2">
<span class="bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-200 px-3 py-1 rounded-full text-sm">
Dark mode ready
</span>
</div>
</div>
</div>
Expected output: The card uses light styles by default and dark styles when the user's system dark mode is enabled.
Class Strategy (Manual Toggle)
// tailwind.config.js - manual toggle dark mode
module.exports = {
darkMode: 'class',
// ...
}
<!-- Toggle button -->
<button id="darkToggle" class="px-4 py-2 bg-gray-200 dark:bg-gray-700 text-gray-800 dark:text-white rounded-lg">
Toggle Dark Mode
</button>
<script>
document.getElementById('darkToggle').addEventListener('click', () => {
document.documentElement.classList.toggle('dark');
});
</script>
<!-- Content (always renders with dark: variants) -->
<div class="bg-white dark:bg-gray-900 p-8 rounded-lg mt-4">
<h3 class="text-gray-900 dark:text-white font-bold">Manual Dark Mode</h3>
<p class="text-gray-600 dark:text-gray-300 mt-2">
Dark mode toggles when the button is clicked, regardless of system preference.
</p>
</div>
Expected output: Toggling the button adds/removes the dark class on the html element, switching between light and dark styles.
Dark Mode Card Example
<div class="max-w-md mx-auto rounded-xl overflow-hidden shadow-lg transition-colors duration-200">
<!-- Card image -->
<div class="h-48 bg-gradient-to-r from-blue-400 to-purple-500 dark:from-blue-800 dark:to-purple-900"></div>
<!-- Card body -->
<div class="p-6 bg-white dark:bg-gray-800 transition-colors">
<div class="flex items-center justify-between">
<span class="text-sm text-blue-600 dark:text-blue-400 font-medium">Category</span>
<span class="text-xs text-gray-400 dark:text-gray-500">3 min read</span>
</div>
<h3 class="mt-2 text-xl font-bold text-gray-900 dark:text-white">
Card Title
</h3>
<p class="mt-2 text-gray-600 dark:text-gray-300 text-sm leading-relaxed">
This card uses dark: variants for background, text, and gradient colors. All colors transition to darker equivalents.
</p>
<div class="mt-4 flex items-center gap-2">
<div class="w-8 h-8 bg-gray-300 dark:bg-gray-600 rounded-full"></div>
<div>
<p class="text-sm font-medium text-gray-900 dark:text-white">Author Name</p>
<p class="text-xs text-gray-400 dark:text-gray-500">Posted June 28</p>
</div>
</div>
</div>
</div>
Expected output: A complete card with image, text, and author section that switches between light and dark color schemes.
Dark Mode Form Elements
<div class="max-w-md mx-auto p-6 bg-white dark:bg-gray-900 rounded-xl transition-colors">
<h2 class="text-lg font-bold text-gray-900 dark:text-white mb-4">Dark Mode Form</h2>
<div class="space-y-4">
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Name</label>
<input type="text"
class="w-full px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg
bg-white dark:bg-gray-800 text-gray-900 dark:text-white
placeholder:text-gray-400 dark:placeholder:text-gray-500
focus:ring-2 focus:ring-blue-500 focus:border-transparent
transition-colors">
</div>
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Bio</label>
<textarea rows="3"
class="w-full px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg
bg-white dark:bg-gray-800 text-gray-900 dark:text-white
placeholder:text-gray-400 dark:placeholder:text-gray-500
focus:ring-2 focus:ring-blue-500 focus:border-transparent
transition-colors">Dark mode textarea</textarea>
</div>
<label class="flex items-center gap-2">
<input type="checkbox"
class="rounded border-gray-300 dark:border-gray-600
text-blue-600 dark:text-blue-400
bg-white dark:bg-gray-800
focus:ring-2 focus:ring-blue-500
transition-colors">
<span class="text-sm text-gray-700 dark:text-gray-300">Remember me</span>
</label>
</div>
</div>
Expected output: Form inputs, textareas, and checkboxes with complete dark mode styling including borders, backgrounds, text, placeholders, and focus rings.
Dark Mode with Transitions
<div class="p-6 bg-white dark:bg-gray-900 min-h-screen transition-colors duration-300">
<h1 class="text-gray-900 dark:text-white transition-colors duration-300">
Smooth Dark Mode Transitions
</h1>
<p class="text-gray-600 dark:text-gray-300 mt-2 transition-colors duration-300">
Adding transition-colors duration-300 to all themed elements creates a smooth dark mode switch.
</p>
</div>
Expected output: When dark mode toggles, colors transition smoothly over 300ms instead of snapping instantly.
Common Mistakes
1. Not Adding dark Mode to the Config
Without darkMode: 'class' or darkMode: 'media' in the config, the dark: variant produces no styles.
2. Inconsistent Dark Color Choices
Using dark:bg-gray-900 for backgrounds and dark:bg-gray-700 for cards creates insufficient contrast. Stick to a consistent dark palette.
3. Forgetting dark: on Interactive States
dark:hover:bg-gray-700 and dark:focus:ring-blue-400 ensure interactive states work in dark mode too.
4. Not Handling Images in Dark Mode
Images with white backgrounds look harsh in dark mode. Add dark:opacity-80 or use CSS filters for images.
5. Ignoring Color Contrast in Dark Mode
What is accessible in light mode may fail contrast requirements in dark mode. Test both themes with a contrast checker.
Practice Questions
What are the two dark mode strategies? media (follows system preference) and class (manual toggle via the
darkclass).How do you enable dark mode with manual toggle?
darkMode: 'class'in tailwind.config.js, then toggledarkclass on the html element.How do you style a button in dark mode? Use dark: variants:
dark:bg-gray-800 dark:text-white dark:border-gray-600.Can dark mode be responsive? Yes:
dark:md:bg-gray-900applies dark background on medium screens and above in dark mode.How do you smooth the dark mode transition? Add
transition-colors duration-300to themed elements.
Challenge
Build a complete dark mode compatible page: navbar with dark:bg-gray-900, hero section with dark gradient, card grid with dark backgrounds, form with dark inputs, and footer. Toggle dark mode with a button.
FAQ
Mini Project
Build a dark mode toggle component: sun/moon icon, button with hover/active states, localStorage persistence, and system preference detection. Apply dark: variants to a full page layout.
What's Next
Now master Custom Fonts for typography customization. Then learn Custom Colors for brand-specific theming.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro