---
title: Dark Mode
description: Implementation guidance with human-benefit reasoning
tags: [ui, accessibility, energy]
dependencies: [accessibility, performance, sustainability]
---

# Dark Mode

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:

```css
:root {
  --bg: #F2E6D9;
  --text: #4A3F35;
}

[data-theme="dark"] {
  --bg: #2C2520;
  --text: #E0D2C4;
}
```

### Respect user preference

Always check the system setting first:

```js
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 `currentColor` to inherit the text color

### Transition smoothly

Add a brief transition so the theme change feels intentional:

```css
body {
  transition: background-color 0.2s ease, color 0.2s ease;
}
```

### Persist the choice

```js
localStorage.setItem('theme', 'dark');
document.documentElement.setAttribute('data-theme', 'dark');
```

## For agents implementing dark mode

When building a UI with dark mode:

1. Define the full color palette for both themes upfront
2. Never hardcode colors — always use custom properties
3. Test all interactive states (hover, focus, active, disabled) in both themes
4. Ensure form inputs, borders, and shadows are visible in both modes
5. Dark mode is not an afterthought — design both themes simultaneously
