Warming up the neural circuits...
Dark mode is a color scheme that uses light text on dark backgrounds. It reduces eye strain in low-light environments, saves battery on OLED screens, and is now a standard feature on every modern website.
dark: PrefixTailwind makes dark mode incredibly simple with the dark: variant prefix. Just add it alongside any utility class:
<div class="bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100">
This div automatically switches colors in dark mode
</div>How it works:
bg-white = light mode (white background)dark:bg-gray-900 = dark mode (near-black background)text-gray-900 = light mode (dark text)dark:text-gray-100 = dark mode (light text)media (Automatic — follows system preference)// tailwind.config.js
module.exports = {
darkMode: 'media', // or just remove this line (default)
// ...
}How it works: Uses prefers-color-scheme media query. If user has dark mode enabled in their OS, your site automatically shows dark mode.
<!-- Automatically switches based on OS setting -->
<div class="bg-white dark:bg-gray-900">
<p class="text-gray-700 dark:text-gray-300">
This adapts to your system theme automatically.
</p>
</div>Pros: Zero , respects user's system preference.
Cons: User can't override per-site. No toggle .
class (Manual toggle — recommended)// tailwind.config.js
module.exports = {
darkMode: 'class', // Enable class-based dark mode
// ...
}How it works: When a parent has class="dark", all dark: utilities inside it activate.
<html class="dark">
<body>
<div class="bg-white dark:bg-gray-900">
<!-- Dark mode is ON because html has class="dark" -->
</div>
</body>
</html>Pros: User can toggle independently. Persist choice with localStorage.
Cons: Requires JavaScript for toggle functionality.
Almost every modern website (GitHub, Twitter, YouTube) uses class-based dark mode. It gives users control. We'll use this approach.
<!-- Add dark class to html element to activate dark mode -->
<html class="dark">
<body class="bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100">
<header class="bg-gray-100 dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700">
<h1 class="text-2xl font-bold">My App
<div class="bg-white dark:bg-gray-800 rounded-xl shadow-md dark:shadow-2xl overflow-hidden">
<div class="p-6">
<h3 class="text-gray-900 dark:text-white font-bold mb-2">Card Title</h3>
<p class="text-gray-600 dark:text-gray-400">
Description text that's readable in both modes.
</
<input
class="w-full px-4 py-2 border border-gray-300 dark:border-gray-600
bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100
rounded-lg focus:ring-2 focus:ring-blue-500 outline-none"
placeholder="Enter your email"
/><nav class="bg-white dark:bg-gray-900 border-b border-gray-200 dark:border-gray-700">
<div class="flex justify-between items-center h-16 px-4">
<h1 class="text-gray-900 dark:text-white font-bold">My App</h1>
<ul class="flex gap-6">
<li><
import React, { useState, useEffect } from 'react';
export function DarkModeToggle() {
const [darkMode, setDarkMode] = useState(false);
// On mount: read from localStorage or system preference
useEffect(()
User clicks toggle
↓
Toggle state changes (light ↔ dark)
↓
Add/remove 'dark' class on <html>
↓
All `dark:` utilities in the page activate/deactivate
↓
Save preference to localStorage
↓
On next visit, preference is restored from localStorage
↓
(If no stored preference, falls back to system setting)<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Dark Mode Demo
<!-- ❌ Wrong: pure inversion is harsh on eyes -->
<div class="bg-black text-white p-6">
<!-- ✅ Right: use soft dark grays -->
<div class="bg-gray-900 text-gray-100 p-6"><!-- Light mode: high contrast -->
<p class="text-gray-900">Primary text</p>
<p class="text-gray-500">Secondary text</p>
<!-- Dark mode: softer contrast -->
<p class="
* {
transition: background-color 0.3s ease, color 0.3s ease, border-color 0.3s ease;
}Or per-element:
<div class="bg-white dark:bg-gray-900 transition-colors duration-300"><!-- Use different images for dark/light mode -->
<img src="logo-light.svg" class="dark:hidden" alt="Logo (light)" />
<img src="logo-dark.svg" class="hidden dark:block" alt="Logo (dark)Check every component in both modes: buttons, inputs, modals, cards, tables, etc.
| Element | Light Mode | Dark Mode |
|---|---|---|
| Page background | bg-white | bg-gray-900 |
| Card background | bg-white | bg-gray-800 |
| Surface (nav, sidebar) | bg-gray-100 | bg-gray-800 |
| Primary text | text-gray-900 | text-gray-100 |
| Secondary text | text-gray-600 | text-gray-400 |
| Border | border-gray-200 | border-gray-700 |
| Shadow | shadow-md | shadow-2xl dark:shadow-black/30 |
| background | |
dark: prefix activates utilities in dark modemedia (automatic) and class (manual toggle)class strategy is the standard for modern websitesdark: to backgrounds, text, borders, shadows, inputsNow that you've mastered Tailwind CSS:
bg-gray-700 |
| Input border | border-gray-300 | border-gray-600 |