Dark mode overview
This page is for designers who add a dark mode to a design, or style pages inside the administration, which has one. It explains the model; the pages linked from each section show the code.
Contents
- The model in four parts
- Light, dark and system
- How admin4 does it
- Two ways for a public design
- What dark mode is not
The model in four parts
- Tokens. Every color is a CSS custom property (
--site-ink,--site-surface), never a literal value in a rule (Design tokens). - Two sets of values. The tokens get light values on
:rootand dark values under a selector or media query. - A switch on
<html>. An attribute such asdata-theme="dark"selects the dark set, or the system setting does. - No flash. The attribute is set before the browser draws anything, by a tiny script file in the head (The theme toggle and the pre-paint guard).
Light, dark and system
A good switch offers three choices: light, dark, and "system" (follow the operating system's setting, also when it
changes while the page is open). Without any choice, a public design can follow the system with
prefers-color-scheme alone (Dark mode with prefers-color-scheme).


How admin4 does it
- Tokens
--a4-*indesign/admin4/stylesheets/components.css; every color token has a dark value underhtml[data-a4-theme="dark"](the rule is enforced by a test: a color token without a dark value fails it). - The choice is stored per user as the preference
admin_color_mode(in the browser'slocalStorageon pages without a signed-in user) and applied bydesign/admin4/javascript/a4_head.js, loaded as a file in the head before the stylesheets. It setsdata-a4-theme(lightordark, what the stylesheets read) anddata-a4-theme-choice(light,darkorsystem, what the switch shows). - The switch in the header (
#a4-theme-toggle) steps light, dark, system; a status region announces each change to screen readers. - Print uses the light tokens: the script sets light before printing and restores the choice afterwards.
color-scheme: darkin the dark block makes form controls and scrollbars dark too.- A frame that has no dark design says
data-a4-modes="light"on<html>and stays light.
Two ways for a public design
| Approach | Effort | Result |
|---|---|---|
Follow the system only (@media (prefers-color-scheme: dark)) | one block of dark token values | automatic, no switch, no script |
| A switch with light, dark, system | tokens, an attribute, one small head script and a button | visitors choose; the choice is remembered |
Start with the first; add the switch when visitors ask for it. Tutorial: add dark mode does both, step by step.
What dark mode is not
- Not
filter: invert(): images and brand colors come out wrong. - Not just a black background: surfaces need several levels (page, card, raised), borders need their own token, and every pair must keep its contrast (Color contrast).
- Not optional for new tokens in the admin: every new color token needs its dark value in the same change.
Related pages
- Design tokens
- admin4 tokens
- 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.