Dark Mode
depends on: accessibility, performance, sustainability
Dark mode is not merely a color swap. It is a considered design choice that respects human physiology, reduces energy consumption, and improves accessibility.
Why dark mode matters
- Eye comfort: Reduced luminance in low-light environments decreases eye strain and fatigue
- Energy savings: On OLED/AMOLED displays, dark pixels consume significantly less power — up to 60% reduction at full dark
- Accessibility: Some users with photosensitivity, migraines, or visual impairments find dark interfaces essential, not optional
- Focus: Lower overall brightness reduces visual noise and helps users concentrate on content
Implementation guidance
Use CSS custom properties
Define your palette once, swap via a data attribute:
:root {
--bg: #F2E6D9;
--text: #4A3F35;
}
[data-theme="dark"] {
--bg: #2C2520;
--text: #E0D2C4;
}
Respect user preference
Always check the system setting first:
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
Then allow manual override stored in localStorage. The user's explicit choice takes precedence over the system setting.
Avoid pure black
Pure black (#000) on OLED screens creates a "smearing" effect during scrolling. Use very dark grays or warm dark tones instead (#1a1a1a, #2C2520).
Ensure sufficient contrast
WCAG 2.1 AA requires a minimum contrast ratio of 4.5:1 for normal text. Test both themes:
- Light mode: dark text on light background
- Dark mode: light text on dark background
Use tools like the WebAIM contrast checker to verify.
Images and media
- Provide dark-mode variants for logos and illustrations where possible
- Use
filter: brightness(0.8)as a fallback for images that are too bright in dark mode - SVG icons should use
currentColorto inherit the text color
Transition smoothly
Add a brief transition so the theme change feels intentional:
body {
transition: background-color 0.2s ease, color 0.2s ease;
}
Persist the choice
localStorage.setItem('theme', 'dark');
document.documentElement.setAttribute('data-theme', 'dark');
For agents implementing dark mode
When building a UI with dark mode:
- Define the full color palette for both themes upfront
- Never hardcode colors — always use custom properties
- Test all interactive states (hover, focus, active, disabled) in both themes
- Ensure form inputs, borders, and shadows are visible in both modes
- Dark mode is not an afterthought — design both themes simultaneously