Dark mode is no longer just a visual extra. Many users now expect websites to either respect their device preference or give them a simple way to switch themes manually. The good news is that adding it does not require a bloated solution.
The PDF breaks the process into two paths: a hand-coded implementation and a WordPress-friendly implementation. Both work best when they use the same basic principles.
How Dark Mode Usually Works
There are two common approaches. The first uses the `prefers-color-scheme` media query so the site follows the visitor's system preference automatically. The second adds a manual toggle and saves that choice with local storage so the theme stays consistent between visits.
In most cases, the strongest implementation combines both. Respect the system setting by default, then let the user override it if they want.
Hand-Coded Sites: Start With CSS Variables
CSS variables make dark mode much easier to manage because the color system lives in one place. Instead of rewriting every selector, you switch the values behind the design tokens.
CSS Variables
:root {
--bg-color: #ffffff;
--text-color: #1c1c1c;
--heading-color: #111111;
--card-bg: #f5f5f5;
--border-color: #e0e0e0;
}
[data-theme='dark'] {
--bg-color: #1a1a2e;
--text-color: #e0e0e0;
--heading-color: #ffffff;
--card-bg: #16213e;
--border-color: #2a2a4a;
}
Respect the System Preference
If you want the site to respond automatically to the operating system theme, add a media query that switches the same variables when the visitor prefers dark mode.
System Preference
@media (prefers-color-scheme: dark) {
:root {
--bg-color: #1a1a2e;
--text-color: #e0e0e0;
--heading-color: #ffffff;
}
}
Add a Toggle Button and Save the Preference
A toggle button gives visitors explicit control. The PDF recommends pairing the button with a small JavaScript helper that reads from `localStorage`, applies the theme, and updates the site without extra libraries.
Theme Toggle
const toggleButton = document.getElementById('theme-toggle');
const root = document.documentElement;
function getInitialTheme() {
const savedTheme = localStorage.getItem('theme');
if (savedTheme) return savedTheme;
return window.matchMedia('(prefers-color-scheme: dark)').matches
? 'dark'
: 'light';
}
function applyTheme(theme) {
if (theme === 'dark') {
root.setAttribute('data-theme', 'dark');
} else {
root.removeAttribute('data-theme');
}
}
applyTheme(getInitialTheme());
toggleButton.addEventListener('click', () => {
const isDark = root.getAttribute('data-theme') === 'dark';
const nextTheme = isDark ? 'light' : 'dark';
applyTheme(nextTheme);
localStorage.setItem('theme', nextTheme);
});
Prevent the Flash of the Wrong Theme
One common issue is a brief flash of the light theme before the dark preference is applied. The cleanest fix is a tiny inline script in the document head that sets the theme before the page fully renders.
WordPress Option A: Use a Plugin
For many WordPress sites, a dark mode plugin is the easiest route. The PDF recommends a plugin-based setup for teams that want minimal technical work and a quick toggle added to the front end.
A plugin approach is especially useful when the site already relies on a theme builder or when the team needs an admin-friendly setup with limited custom coding.
WordPress Option B: Add It Manually
If you want tighter control, you can add the toggle markup to the theme, load a dedicated CSS file for dark-mode variables, enqueue the JavaScript, and print a small anti-flash script in `wp_head`. That approach gives you more control over performance and styling.
functions.php
function child_theme_enqueue_scripts() {
wp_enqueue_style(
'dark-mode-styles',
get_stylesheet_directory_uri() . '/css/dark-mode.css',
array(),
'1.0.0'
);
wp_enqueue_script(
'dark-mode-script',
get_stylesheet_directory_uri() . '/js/dark-mode.js',
array(),
'1.0.0',
true
);
}
add_action('wp_enqueue_scripts', 'child_theme_enqueue_scripts');
Common Problems to Watch For
- Images can feel too bright in dark mode and may need a small brightness adjustment.
- The theme can reset on navigation if the inline anti-flash script runs too late.
- Hardcoded block colors in WordPress can override your variable-based color system.
The cleanest dark mode setups stay lightweight, respect user preference, and avoid hardcoded color values throughout the site.
Final Thoughts
Dark mode improves the overall experience when it feels deliberate rather than bolted on. For hand-coded websites, CSS variables and a small script are usually enough. For WordPress, a plugin or a focused custom implementation can both work well depending on how much control you want.
Either way, the goal is the same: make the website feel more modern, more considerate, and more comfortable to use.