Dark Mode Design Guidelines: Beyond Inverting Colors
Dark mode is more than swapping white for black. Proper dark theme design requires adjusted contrast ratios, desaturated colors, and thoughtful elevation mapping to maintain readability and visual hierarchy.
Key Takeaways
- Simply inverting a light theme produces eye-straining contrast, muddy colors, and broken visual hierarchy.
- Use a tiered gray system instead of pure black:
- Vibrant colors that look great on white can feel harsh on dark backgrounds.
- Avoid pure white (#FFFFFF) text on dark backgrounds.
- Define all colors as CSS custom properties with two value sets.
Color Palette Generator
Why Dark Mode Needs Special Attention
Simply inverting a light theme produces eye-straining contrast, muddy colors, and broken visual hierarchy. Dark mode is a parallel design system that shares the same structure but uses different rules.
Background Layers
Use a tiered gray system instead of pure black:
| Layer | Light Mode | Dark Mode |
|---|---|---|
| Surface 0 (page) | #FFFFFF | #121212 |
| Surface 1 (card) | #F9FAFB | #1E1E1E |
| Surface 2 (elevated) | #F3F4F6 | #2A2A2A |
| Surface 3 (modal) | #E5E7EB | #333333 |
Higher elevation surfaces are lighter in dark mode — the opposite of light mode where shadows create depth. This simulates light falling on raised surfaces.
Color Adjustments
Vibrant colors that look great on white can feel harsh on dark backgrounds. Reduce saturation by 10-20% and increase lightness slightly. For example, a primary blue of hsl(220, 90%, 50%) in light mode becomes hsl(220, 70%, 65%) in dark mode.
Text Contrast
Avoid pure white (#FFFFFF) text on dark backgrounds. It creates excessive contrast that causes visual fatigue during long reading sessions. Use #E0E0E0 or #D1D5DB for body text and reserve near-white for headings and emphasis.
Implementation Strategy
Define all colors as CSS custom properties with two value sets. Use prefers-color-scheme: dark as the default and provide a manual toggle that stores preference in localStorage. Apply the class to the element before first paint to prevent FOUC.