Every palette has a light set and a dark set. theme.mode decides which set readers see.
| Mode | Behavior |
|---|---|
light |
The default. Readers always see light mode. |
dark |
Readers always see dark mode. |
system |
Follows the reader's operating system setting. Shows a toggle unless you turn it off. |
Lock the site to one mode
theme:
mode: dark
A locked site writes only the colors for that mode and shows no toggle. The build checks contrast for that mode only.
Follow the reader's setting
theme:
mode: system
The site starts in the mode the reader's system prefers. A button in the masthead switches between light and dark. The browser stores the choice under the shoalrun-color-mode local storage key on that device, and the choice overrides the system setting.
To follow the system setting without a toggle, set toggle: false:
theme:
mode: system
toggle: false
toggle: true works only with mode: system. The build checks contrast for both modes.
Custom callout tones need dark colors before a site can show dark mode. The callout guide explains the dark block.
How it works
mode: systemwrites both color sets to/assets/palette.css. The dark set applies inside@media (prefers-color-scheme: dark).- The page sets
<meta name="color-scheme">tolight,dark, orlight dark, so scrollbars and form controls match. - With the toggle on,
/assets/mode.jsloads in the page head before first paint. It reads the saved choice and setsdata-mode="light"ordata-mode="dark"on thehtmlelement, so the page doesn't flash the wrong colors. - The toggle is a
buttonwitharia-pressed. Screen readers announce it as "Dark mode", pressed or not pressed. - Without JavaScript, the toggle stays hidden and the system setting still applies.
- If the browser blocks storage, the toggle still works for the current page.
Target a mode in project CSS with [data-mode="dark"], or with prefers-color-scheme for readers who have not used the toggle:
@media (prefers-color-scheme: dark) {
:root:not([data-mode="light"]) .doc-card-icon { opacity: .9; }
}
:root[data-mode="dark"] .doc-card-icon { opacity: .9; }
Code blocks stay dark in both modes. By default, their syntax colors come from the palette's dark set. The code block guide explains how to change it.