
How to add dark mode to a WordPress website?
You can add dark mode to a WordPress website in three main ways: install a dark mode plugin such as WP Dark Mode, write CSS that uses the prefers-color-scheme media query to follow each visitor's system setting, or build a custom toggle button with a little JavaScript that switches themes and remembers the visitor's choice. Block theme users can also offer a dark style variation that site editors can switch to in the Site Editor.
Dark mode has become a standard feature on phones, operating systems, and apps, and many visitors now expect websites to respect it. In this guide, you'll learn the pros and cons of each approach, see step-by-step instructions for the plugin method, and get working code for a system-aware dark mode and a toggle that avoids the annoying "flash" of light content on page load.
Why Add Dark Mode to Your Website?
Dark mode isn't just a trend. It offers real benefits for many visitors:
- Comfort in low light: Dark backgrounds can be easier on the eyes when reading at night.
- User preference: Many people set their devices to dark mode and appreciate sites that match.
- Battery savings: On devices with OLED screens, dark pixels use less power.
- Modern feel: A well-designed dark theme can make your site feel polished and current.
- Accessibility options: Some users with light sensitivity find dark interfaces more comfortable.
That said, dark mode isn't automatically better for everyone. Some people find light text on dark backgrounds harder to read for long periods. The best approach is to respect the visitor's system preference and, ideally, let them switch.
Approach 1: Use a Dark Mode Plugin
The quickest way to add dark mode is with a plugin. Popular options include:
- WP Dark Mode: One of the most widely used dark mode plugins, with a floating toggle switch, automatic OS detection, and several preset color schemes.
- Droit Dark Mode: A lightweight alternative with toggle styles and presets.
- Dark Mode Toggle: A simple plugin that adds a switch using a CSS inversion approach.
How to Set Up a Dark Mode Plugin
Using WP Dark Mode as an example, the general steps are:
-
Install the plugin: Go to Plugins > Add New Plugin, search for "WP Dark Mode," and click Install Now, then Activate.
-
Open the settings: Find the plugin's menu item in your dashboard sidebar.
-
Enable frontend dark mode: Turn on dark mode for your website. You can usually also enable it for the admin dashboard separately.
-
Choose OS-aware behavior: Enable the option that follows the visitor's operating system preference, so people with dark mode enabled on their device see your dark theme automatically.
-
Pick a color preset: Choose a dark color scheme that complements your brand, or customize the background, text, and link colors.
-
Configure the toggle: Choose the switch style and position, such as a floating button in the bottom corner, or place it in your menu.
-
Exclude elements if needed: Many plugins let you exclude certain elements, such as logos or product images, from color changes.
-
Test your site: Visit your pages in both modes and check headers, forms, buttons, and images.
Pros and Cons of Plugins
Pros: Fast setup, no coding, built-in toggle, and settings that non-developers can manage.
Cons: Plugins often apply dark colors automatically by recalculating or inverting colors, which may not match your design perfectly. They also add extra scripts and styles. Premium features, such as advanced presets or per-page controls, may require a paid plan.
A plugin is a great choice if you want dark mode quickly and your design is fairly standard.
Approach 2: Follow the System Setting With CSS
If you'd rather have full control over the colors and avoid extra plugins, CSS can do most of the work. The prefers-color-scheme media query detects whether a visitor's device is set to dark mode.
Using Block Theme Color Presets
Block themes define their colors in theme.json, and WordPress turns them into CSS custom properties like --wp--preset--color--base and --wp--preset--color--contrast. You can redefine those variables for dark mode, and every block that uses them updates automatically.
Check your theme's palette slugs first. In the Site Editor, go to Styles > Colors > Palette, or look at the theme's theme.json. Twenty Twenty-Four and Twenty Twenty-Five, for example, use slugs such as base and contrast.
Then add CSS like this under Appearance > Editor > Styles > Additional CSS, or in your child theme's stylesheet:
@media (prefers-color-scheme: dark) {
:root {
--wp--preset--color--base: #0f172a;
--wp--preset--color--contrast: #e2e8f0;
--wp--preset--color--accent-1: #60a5fa;
color-scheme: dark;
}
img:not([src$=".svg"]) {
filter: brightness(0.92);
}
}
The color-scheme: dark declaration tells the browser to render form controls and scrollbars in dark style too. Replace the slugs with the ones your theme actually uses.
Using Plain CSS for Classic Themes
Classic themes often hard-code colors in their stylesheets. In that case, you'll need to override the relevant selectors directly. Use your browser's Inspect tool to find the main background and text elements:
@media (prefers-color-scheme: dark) {
body,
.site,
.site-header,
.site-footer {
background-color: #121212;
color: #e5e5e5;
}
a {
color: #8ab4f8;
}
.entry-content blockquote {
border-color: #444444;
color: #cfcfcf;
}
input,
textarea,
select {
background-color: #1e1e1e;
color: #e5e5e5;
border-color: #3a3a3a;
}
}
This approach is lightweight and has no JavaScript at all. The downside is that visitors can't choose; the site always follows their device setting.
Approach 3: Build a Custom Dark Mode Toggle
For the best experience, combine system detection with a toggle button that lets visitors override it. Here's a complete, lightweight setup you can add to a child theme or a small custom plugin.
Step 1: Prevent the Flash of Light Mode
If you apply dark mode with JavaScript after the page loads, visitors may briefly see the light version before it switches. To avoid this, run a tiny script in the <head> before the page renders. Add this to your child theme's functions.php:
function sajjad_dark_mode_head_script() {
$script = "(function () {
try {
var stored = localStorage.getItem('sajjad-theme');
var prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
var theme = stored ? stored : (prefersDark ? 'dark' : 'light');
document.documentElement.setAttribute('data-theme', theme);
} catch (e) {}
})();";
wp_print_inline_script_tag( $script );
}
add_action( 'wp_head', 'sajjad_dark_mode_head_script', 1 );
This checks whether the visitor previously chose a theme. If not, it falls back to the system preference, and it sets a data-theme attribute on the <html> element immediately. The try block protects against browsers where localStorage is blocked.
Step 2: Add the Toggle Button
Register a shortcode so you can place the toggle anywhere, such as in a Shortcode block in your header:
function sajjad_dark_mode_toggle_shortcode() {
return sprintf(
'<button type="button" class="sajjad-theme-toggle" aria-pressed="false" aria-label="%s"><span class="sajjad-theme-toggle__icon" aria-hidden="true"></span><span class="sajjad-theme-toggle__text">%s</span></button>',
esc_attr__( 'Toggle dark mode', 'sajjad' ),
esc_html__( 'Dark mode', 'sajjad' )
);
}
add_shortcode( 'dark_mode_toggle', 'sajjad_dark_mode_toggle_shortcode' );
In a block theme, go to Appearance > Editor, open your Header template part, and insert a Shortcode block containing [dark_mode_toggle]. In a classic theme, add the shortcode to a widget, or call echo do_shortcode( '[dark_mode_toggle]' ); in header.php.
Step 3: Add the Toggle JavaScript
Create a file at assets/js/dark-mode.js in your child theme:
(function () {
var root = document.documentElement;
var storageKey = "sajjad-theme";
function applyTheme(theme) {
root.setAttribute("data-theme", theme);
document
.querySelectorAll(".sajjad-theme-toggle")
.forEach(function (button) {
button.setAttribute(
"aria-pressed",
theme === "dark" ? "true" : "false",
);
});
}
function currentTheme() {
return root.getAttribute("data-theme") === "dark" ? "dark" : "light";
}
document.addEventListener("DOMContentLoaded", function () {
applyTheme(currentTheme());
document
.querySelectorAll(".sajjad-theme-toggle")
.forEach(function (button) {
button.addEventListener("click", function () {
var next = currentTheme() === "dark" ? "light" : "dark";
applyTheme(next);
try {
localStorage.setItem(storageKey, next);
} catch (e) {}
});
});
});
// Follow system changes if the visitor hasn't made a choice.
var media = window.matchMedia("(prefers-color-scheme: dark)");
media.addEventListener("change", function (event) {
try {
if (localStorage.getItem(storageKey)) {
return;
}
} catch (e) {}
applyTheme(event.matches ? "dark" : "light");
});
})();
Then enqueue the script and a stylesheet in functions.php:
function sajjad_dark_mode_assets() {
$dir = get_stylesheet_directory();
$uri = get_stylesheet_directory_uri();
wp_enqueue_script(
'sajjad-dark-mode',
$uri . '/assets/js/dark-mode.js',
array(),
filemtime( $dir . '/assets/js/dark-mode.js' ),
array(
'in_footer' => true,
'strategy' => 'defer',
)
);
wp_enqueue_style(
'sajjad-dark-mode',
$uri . '/assets/css/dark-mode.css',
array(),
filemtime( $dir . '/assets/css/dark-mode.css' )
);
}
add_action( 'wp_enqueue_scripts', 'sajjad_dark_mode_assets' );
The array syntax for the fifth parameter of wp_enqueue_script(), including the defer strategy, is supported in WordPress 6.3 and later.
Step 4: Add the Dark Mode Styles
Create assets/css/dark-mode.css. Because the head script sets data-theme on the <html> element, all your dark styles can target [data-theme="dark"]:
:root[data-theme="dark"] {
--wp--preset--color--base: #0f172a;
--wp--preset--color--contrast: #e2e8f0;
--wp--preset--color--accent-1: #60a5fa;
color-scheme: dark;
}
/* Classic theme fallbacks */
:root[data-theme="dark"] body {
background-color: var(--wp--preset--color--base, #0f172a);
color: var(--wp--preset--color--contrast, #e2e8f0);
}
:root[data-theme="dark"] a {
color: #93c5fd;
}
/* Toggle button */
.sajjad-theme-toggle {
display: inline-flex;
align-items: center;
gap: 0.5rem;
padding: 0.4rem 0.8rem;
border: 1px solid currentColor;
border-radius: 999px;
background: transparent;
color: inherit;
font: inherit;
cursor: pointer;
}
.sajjad-theme-toggle__icon::before {
content: "\263E";
}
:root[data-theme="dark"] .sajjad-theme-toggle__icon::before {
content: "\2600";
}
.sajjad-theme-toggle:focus-visible {
outline: 2px solid currentColor;
outline-offset: 2px;
}
The icon uses Unicode characters for a moon and a sun, so no image files are needed. Adjust the palette slugs to match your theme.
Since the preset custom properties are used by every block that picks a palette color, redefining them switches most of a block theme's design at once. Anything with hard-coded colors, such as custom HTML or plugin output, may need extra rules.
Approach 4: Offer a Dark Style Variation (Block Themes)
Block themes support style variations, which are alternative sets of colors and fonts stored in the theme's styles folder. Many themes, including recent default themes, ship with dark variations you can select under Appearance > Editor > Styles.
This changes the site's design for everyone, not per visitor, so it's not a true dark mode toggle. But it's useful if you want your whole site to have a dark design, or as a starting point for choosing your dark palette. You can note the colors from a dark variation and reuse them in the CSS from Approach 3.
If you're building your own theme, a variation file like styles/dark.json might look like this:
{
"$schema": "https://schemas.wp.org/trunk/theme.json",
"version": 3,
"title": "Dark",
"settings": {
"color": {
"palette": [
{ "slug": "base", "color": "#0f172a", "name": "Base" },
{ "slug": "contrast", "color": "#e2e8f0", "name": "Contrast" },
{ "slug": "accent-1", "color": "#60a5fa", "name": "Accent 1" }
]
}
}
}
Designing a Good Dark Theme
Simply inverting colors rarely looks good. Follow these guidelines for a comfortable dark design:
Avoid pure black and pure white: Very dark gray or navy backgrounds (like #121212 or #0f172a) with off-white text are easier on the eyes than #000000 and #ffffff.
Check contrast: Aim for at least a 4.5:1 contrast ratio for body text, following WCAG guidelines. Tools like the WebAIM Contrast Checker help you test colors.
Soften bright accents: Saturated colors can look harsh on dark backgrounds. Use lighter, slightly desaturated versions of your brand colors.
Handle images and logos: A dark logo can disappear on a dark background. Provide a light version of the logo, or add a subtle background behind it. Slightly dimming photos can reduce glare.
Use elevation carefully: In dark designs, surfaces that sit "higher," like cards and menus, are usually slightly lighter than the background rather than having heavy shadows.
Style forms and code blocks: Inputs, tables, and code snippets are often forgotten. Make sure they're readable in both modes.
Test embeds and plugins: Embedded videos, maps, and third-party widgets may not adapt. Decide whether to leave them as they are or add targeted styles.
Testing Dark Mode
Before you consider the job done, test thoroughly:
- Switch your operating system to dark mode and load your site in a fresh private window to confirm automatic detection.
- Use browser developer tools: Chrome and Edge DevTools can emulate
prefers-color-schemeunder the Rendering panel, and Firefox has a similar option. - Click the toggle and reload the page to confirm the choice is remembered.
- Check key pages: Home page, blog posts, archive pages, forms, checkout, and 404 pages.
- Test on mobile: Make sure the toggle is easy to reach and tap.
- Clear caches: If you use a caching plugin, clear it after adding the code. The approach above is compatible with page caching because the theme is chosen in the browser, not on the server.
FAQ: Adding Dark Mode to WordPress
Yes. You can use CSS with the prefers-color-scheme media query to follow the visitor's system setting, and add a small JavaScript toggle if you want visitors to switch manually.
A CSS-based dark mode has virtually no performance impact. Plugins add some extra scripts and styles, but a well-built plugin usually has only a small effect.
Run a tiny inline script in the head, before the page renders, that reads the saved preference or system setting and sets a data-theme attribute on the html element.
Yes, as long as the theme is applied in the browser with CSS and JavaScript. Avoid server-side solutions that change the HTML based on cookies, since cached pages would show the same version to everyone.
Upload a light version of your logo and swap it with CSS when dark mode is active, or give the logo a subtle background so it stays visible on dark colors.
Yes. Some dark mode plugins include an admin dark mode, and WordPress also offers built-in admin color schemes under Users > Profile, although none of them are fully dark.
It can help some users, especially those with light sensitivity, but it isn't better for everyone. Offering a choice and maintaining good contrast in both modes is the most accessible approach.
Conclusion
Adding dark mode to a WordPress website is easier than it looks. A plugin like WP Dark Mode gives you a toggle and automatic detection in minutes. If you want full control and minimal overhead, a few lines of CSS using prefers-color-scheme will follow each visitor's system setting, and a small script adds a toggle that remembers their choice without a flash of light content.
Whichever approach you choose, put care into the dark palette itself: avoid pure black, keep contrast high, soften bright accents, and check logos, images, and forms. Test in both modes on desktop and mobile, clear your caches, and you'll give your visitors a comfortable reading experience at any time of day.


