In short
Design dark mode by building it into the semantic color token layer from the start — the same semantic names (text, surface, border) simply map to different underlying scale values in light versus dark — rather than treating dark mode as an entirely separate design pass requiring duplicate decisions across every screen.
The mistake that doubles the work
Treating dark mode as a second, separate design effort — redesigning each screen from scratch for a dark background — genuinely does double the work, because every layout, spacing, and content decision has to be re-verified in a second context. The efficient alternative treats dark mode as a different mapping of the same semantic system, not a parallel design process.
Building the semantic layer to support both
If your color system already separates primitive scale values from semantic tokens (color-surface-primary, color-text-primary), dark mode becomes a second mapping of those same semantic names onto different scale values — color-surface-primary might be gray-50 in light mode and gray-900 in dark mode, but every component that references the semantic token automatically adopts the correct value in either mode without being redesigned.
What doesn't automatically transfer
Layout, spacing, and typography generally transfer directly between light and dark mode without adjustment. What does need specific attention: shadows (which read very differently or become invisible on dark backgrounds and often need to be replaced with subtle borders or lighter overlay treatments instead), and saturated colors (which can appear to vibrate or glow uncomfortably against a dark background and often need slightly reduced saturation in their dark-mode mapping).
Contrast needs separate verification
A semantic pairing that passes accessibility contrast in light mode isn't automatically compliant in dark mode — each mapping needs its own contrast check, since the relationship between two colors doesn't simply invert cleanly when the underlying values change.
Testing real screens, not just the palette
Before considering dark mode complete, review actual populated screens — not just an isolated palette or a single component — in dark mode, since problems like a saturated accent color that looks fine in isolation but overwhelms a real, content-dense screen are easy to miss when only checking the underlying token values in isolation.
Handling images and content
Photography and illustrations designed for a light background sometimes need a dark-mode-specific treatment (a subtle border, a different crop, or an alternate asset) if they don't read well when surrounded by dark UI — decide this on a case-by-case basis rather than assuming all existing imagery transfers cleanly.
The payoff of doing it this way
When dark mode is built as a token mapping rather than a parallel design, adding it to an existing product is primarily a systematic token and contrast exercise rather than a full redesign — and any future third theme (a high-contrast mode, a seasonal theme) becomes similarly cheap, since the same mapping mechanism extends to it.
Further reading: the W3C Design Tokens Community Group publishes primary guidance behind the practices covered here.
Common questions
Does dark mode require redesigning every screen?
Not if the color system is built with a semantic token layer — dark mode becomes a different mapping of the same semantic names, and most screens adopt it automatically without being redesigned individually.
What needs special attention in dark mode beyond color?
Shadows, which often need replacing with subtle borders or overlays, and saturated accent colors, which can appear to glow or vibrate uncomfortably and often need a slightly desaturated dark-mode mapping.
Can I reuse the same contrast checks from light mode for dark mode?
No — each semantic color pairing needs its own contrast verification in dark mode, since the relationship between two colors doesn't automatically invert cleanly when the underlying values change.