Darkness is not the objective
Dark mode succeeds when hierarchy and comfort survive a change in luminance. Replacing white with black and mechanically inverting every other value usually produces glare, muddy borders, and accents that feel brighter than the content they are meant to support.
Start from semantic tokens rather than component-specific colors. A token describes a job, so the value can change without rewriting the component vocabulary.
:root {
color-scheme: light dark;
--surface: #f6f4ef;
--surface-raised: #ffffff;
--text: #1b1b19;
--muted: #68675f;
--border: #d8d5cc;
--accent: #315ea8;
}
@media (prefers-color-scheme: dark) {
:root {
--surface: #151513;
--surface-raised: #1e1e1b;
--text: #f2f0e8;
--muted: #aaa79d;
--border: #393832;
--accent: #8bb8ff;
}
}
Avoid making every raised surface lighter by the same amount. Elevation, grouping, and emphasis can also be communicated through spacing and borders. Dark themes become noisy when every card glows against the page.
Review more than the palette
| Context | What to inspect | Common failure |
|---|---|---|
| Long article | Reading comfort and link visibility | Pure white text creates glare |
| Code block | Syntax contrast and overflow | Muted tokens disappear |
| Disabled control | State remains identifiable | Control looks enabled |
| External image | Edge treatment | Bright image dominates the page |
| Focus state | Keyboard location is obvious | Outline blends into the border |
| Error state | Meaning survives without color | Red is the only signal |
- Text remains readable at reduced brightness.
- Links do not rely on color alone.
- Borders remain visible without becoming luminous.
- Native controls follow
color-scheme. - Theme choice survives navigation and reload.
- Focus and error states remain unambiguous.
- Screenshots are reviewed on desktop and mobile.
- Motion respects reduced-motion preferences.
Test transitions and exceptions
Theme switching can expose a flash before styles load, a stale browser control color, or a chart that was rendered with the previous palette. Test first navigation, hard refresh, back navigation, and a system theme change while the page is open.
Should every image be dimmed?
No. Automatic dimming changes the artwork and can make photographs inaccurate. Prefer a subtle border or surrounding surface, and reserve dimming for decorative assets you control. If an image is essential to the argument, preserve its intended values.
Good dark mode is not a separate visual identity. It is the same hierarchy expressed with a different light budget.