Dark Mode and Color Palette Design
Purpose
This best practice document outlines RECOMMENDED practices for designing dark mode themes and constructing tokenized color systems. Standardizing contrast, visual hierarchy, and color adjustments across display modes minimizes optical fatigue, preserves accessibility conformance, and ensures consistent rendering on modern electronic displays.
Normative language (MUST, MUST NOT, SHOULD, MAY) follows RFC 2119 semantics.
Rules
R-1: Theme Implementation and OS Preference
Applications SHOULD support both light and dark visual themes.
- Visual theme switching SHOULD automatically respond to the host operating system's configuration via CSS
@media (prefers-color-scheme) - When a manual override toggle is provided, the selection MUST persist locally (e.g., via browser
localStorageor server profile preference) to avoid resetting on page refresh
R-2: Dark Mode Palette Construction
Dark themes SHOULD NOT use pure black (#000000) for primary, high-area background zones.
- Primary dark mode background colors SHOULD utilize desaturated off-blacks or charcoal tones (e.g., HSL neutral-dark values,
#121212,#1e1e1e) to reduce screen glare and eye strain - Text in dark mode SHOULD NOT use pure white (
#FFFFFF) — use high-contrast off-whites or light grays instead to prevent visual vibration - Accent and brand colors SHOULD be adjusted (lightened or slightly desaturated) when transitioning to dark mode to ensure they maintain sufficient contrast without causing optical bleeding/halo effects
- UI elevation (stacking hierarchy) in dark mode SHOULD be indicated by applying lighter color overlays or background values on top-level elements (the closer the element is to the user, the lighter its color)
R-3: Design Token Abstraction
Color variables MUST be declared as semantic design tokens (variables) rather than static, hardcoded hex values.
- Token definitions SHOULD represent element roles (e.g.,
--color-bg-primary,--color-text-secondary,--color-accent) rather than literal color definitions (e.g.,--color-gray-100,--color-blue-500)
Examples
HSL Theme Token Configuration
/* Valid: Color configuration using semantic CSS Custom Properties */
:root {
--color-bg-primary: hsl(220, 15%, 98%);
--color-text-primary: hsl(220, 20%, 12%);
--color-accent: hsl(210, 100%, 50%);
--color-elevation-1: hsl(220, 15%, 95%);
}
@media (prefers-color-scheme: dark) {
:root {
--color-bg-primary: hsl(220, 15%, 8%); /* Off-black */
--color-text-primary: hsl(220, 10%, 90%); /* Off-white */
--color-accent: hsl(210, 100%, 65%); /* Slightly desaturated accent */
--color-elevation-1: hsl(220, 15%, 12%); /* Lighter background for elevation */
}
}
/* Invalid: Static hex colors hardcoded in components */
.card-component {
background-color: #ffffff;
color: #333333;
}
References
- W3C WCAG Contrast Minimum (SC 1.4.3)
- W3C Advanced Perceptual Contrast Algorithm (APCA) Draft Spec
- W3C Design Tokens Format Specification (Community Draft)
- ISO 9241-307:2008 — Analysis and compliance test methods for electronic visual displays
- ISO 9241-391:2016 — Requirements, analysis and compliance methods for the reduction of photosensitive seizures
- Material Design 3 Color System
- Apple Human Interface Guidelines — Color
Rationale
Why avoid pure black (#000000) backgrounds? Sighted users with astigmatism (roughly 30-40% of the population) experience "haloing" or "bleeding" when reading high-contrast white text on a pure black background. Softening the contrast to charcoal tones minimizes iris dilation and eye fatigue.
Why adjust accent colors for dark mode? Accent colors designed for light mode (e.g., dark blue) have poor contrast and readability against dark backgrounds. Conversely, highly saturated colors designed for light mode (e.g., hot pink) bleed visually in dark environments. Standardizing lightened or desaturated variants for dark themes guarantees visual clarity.
Version History
| Version | Date | Change |
|---|---|---|
| 1.0.0 | 2026-06-16 | Initial definition; gold standard |