The Clean Way to Implement Dark Mode
There are many ways to add dark mode — but most beginners do it wrong. The right way uses CSS custom properties (variables) and a single data-theme attribute on the <html> element. Change one attribute, and your entire website changes theme instantly.
Step 1 — Define CSS Variables
/* Light theme — default */
:root {
--bg: #ffffff;
--text: #1a1a1a;
--card: #f5f5f5;
}
/* Dark theme — activated by data attribute */
[data-theme="dark"] {
--bg: #0d0d0d;
--text: #e8e8e8;
--card: #1a1a1a;
}
/* Use variables everywhere */
body { background: var(--bg); color: var(--text); }
.card { background: var(--card); }
Step 2 — Add Smooth Transitions
Without transitions, the theme change is an instant flash. One CSS rule fixes this:
*, *::before, *::after {
transition:
background-color 0.3s ease,
color 0.3s ease,
border-color 0.3s ease;
}
Step 3 — The Toggle JavaScript
function applyTheme(theme) {
if (theme === 'dark') {
document.documentElement.setAttribute('data-theme', 'dark');
} else {
document.documentElement.removeAttribute('data-theme');
}
}
document.getElementById('toggle').addEventListener('click', () => {
const isDark = document.documentElement.getAttribute('data-theme') === 'dark';
const newTheme = isDark ? 'light' : 'dark';
applyTheme(newTheme);
localStorage.setItem('theme', newTheme); // Remember choice
});
Step 4 — Detect OS Preference
function initTheme() {
const saved = localStorage.getItem('theme');
if (saved) { applyTheme(saved); return; }
// Fall back to OS preference
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
applyTheme(prefersDark ? 'dark' : 'light');
}
initTheme(); // Run on page load
The priority order is: saved preference → OS setting → light (default).
This is a preview. The full ebook includes the animated pill toggle button CSS, a complete demo page showing dark mode applied to inputs, cards, and forms, and a step-by-step guide for adding dark mode to an existing website.
