Tutorial: add dark mode
This tutorial is for designers who add a dark mode to a design that has only a light one. Part A follows the system setting (no script); part B adds a switch. Allow two to four hours, most of it in step 1.
Contents
- Step 1: colors into tokens
- Step 2: dark values for the system setting
- Step 3: images and logos
- Step 4: a switch
- Step 5: test
Step 1: colors into tokens
- List every color in your stylesheets:

grep -n -o -E "#[0-9a-fA-F]{3,8}\b|rgba?\([^)]*\)" extension/mytheme/design/mytheme/stylesheets/*.css | sort | uniq -c | sort -rn- Group them by role: text, muted text, page background, card background, border, accent, focus.
- Define one token per role in
tokens.cssand replace every literal withvar(--site-...)(Design tokens). Near-identical grays become one token. - Reload: the light page must look the same as before.
Step 2: dark values for the system setting
Add to tokens.css:
@media (prefers-color-scheme: dark) {
:root:not([data-theme="light"]) {
color-scheme: dark;
--site-ink: #e8ebf0;
--site-muted: #a3abb9;
--site-surface: #171c25;
--site-card: #1b212c;
--site-line: #2e3644;
--site-accent: #7fb3f0;
--site-focus: #7fb3f0;
}
}Set your operating system to dark and reload. Measure the contrast of every text token on every surface token (Color contrast).
Step 3: images and logos
- Logo: a version for dark backgrounds, or an SVG drawn in
currentColor(SVG images). - Icons as CSS masks follow the text color.
- Shadows: darker and subtler in dark mode, or a border instead.
Step 4: a switch
Copy the dark values into a second block for an explicit choice:
:root[data-theme="dark"] { color-scheme: dark; --site-ink: #e8ebf0; /* the same values as above */ }Add
javascript/theme-guard.jsfrom The theme toggle and the pre-paint guard and load it in the head, before the stylesheets:ezscript( array( 'theme-guard.js' ) ) ezcss_load( array( 'tokens.css', 'mytheme.css' ) )Add the button in the header and its click handler in your main script file (same page).
Translate the button's labels.
Step 5: test
Use the dark mode checklist. In short: every page type in light and dark, at 1440 px and 960 px with scale 2; no white boxes; contrast measured; reload keeps the choice; no flash on load; print is light.

Related pages
- Dark mode overview
- Dark mode with prefers-color-scheme
- Checklist: dark mode
- Free documentation: this page is free to copy, translate and improve under the GNU FDL 1.3.
Become an Exponential Partner
Partners share their information, provide funding, contribute back and develop the products with us, and that is how Exponential grows. A partner website and dashboard are planned for mid-2027: please become a partner today to speed up our growth rate and land new features faster.