Dark Mode CSS: Implementation Strategies and Common Pitfalls
Implement dark mode correctly with CSS custom properties, media queries, and user preference storage. Avoid the common pitfalls that cause flash of wrong theme, poor contrast, and inconsistent colors.
Key Takeaways
- Define all colors as custom properties and swap them for dark mode:
- The biggest dark mode pitfall is a bright flash before the dark theme loads.
- Pure color inversion**: `filter: invert(1)` breaks images and videos
- Images need special treatment in dark mode.
- This script must be synchronous (not deferred) and must read from `localStorage` or `matchMedia`.
Implementation Approaches
| Approach | Pros | Cons |
|---|---|---|
prefers-color-scheme only |
Automatic, zero JS | No manual toggle |
Class toggle (.dark) |
Manual control, JS toggle | Requires JS, FOUC risk |
| Combined | Best of both | More complex |
Custom Properties Strategy
Define all colors as custom properties and swap them for dark mode:
:root {
--bg-primary: #ffffff;
--text-primary: #1a1a2e;
--border: #e2e8f0;
}
.dark {
--bg-primary: #0f172a;
--text-primary: #e2e8f0;
--border: #334155;
}
Preventing Flash of Wrong Theme (FOWT)
The biggest dark mode pitfall is a bright flash before the dark theme loads. The fix requires an inline script in that applies the theme class before any rendering occurs. This script must be synchronous (not deferred) and must read from localStorage or matchMedia.
Common Pitfalls
- Pure color inversion:
filter: invert(1)breaks images and videos - Too dark backgrounds: Pure
#000is harsh — use dark gray (#0f172a) - Insufficient contrast: Test all text/background combinations in both modes
- Hardcoded colors: Any color not using custom properties breaks in dark mode
- Image backgrounds: Light images need dark overlays in dark mode
Image Handling
Images need special treatment in dark mode. Photos are usually fine, but screenshots, diagrams, and logos with light backgrounds look harsh. Solutions include reducing brightness, adding subtle borders, or providing alternate dark-mode image variants.
Generate dark mode color schemes with the Peasy color tools — automatic contrast checking for both light and dark themes.