Back
🌙
Implementing Dark Mode in a Web App
Medium
16 items
·
1 hour
testuser
Published 1 month ago
This checklist guides frontend developers and designers through a practical, accessible dark mode implementation. It covers CSS variables, system preference detection, persistence, image handling, third-party theming, and testing.
Progress
0 / 16
- Define semantic CSS custom properties for color roles — Create tokens like --bg, --surface, --text, --muted to avoid hard-coded colors.
- Create default (light) values in :root and dark values under a theme selector — Use :root for light and .theme-dark or [data-theme="dark"] for dark values.
- Apply prefers-color-scheme media query for system preference fallback — Use @media (prefers-color-scheme: dark) to provide an initial dark set when no user choice exists.
- Apply a theme class or data-attribute to the document root — Toggle .theme-dark or set data-theme on <html> so rules and components easily scope to the theme.
- Implement a JavaScript initializer to set the starting theme — Read localStorage, then prefer system setting, then default; then set the root attribute/class.
- Add an accessible theme toggle button to the UI — Ensure visible label, keyboard focus, and aria-pressed or aria-label that updates on change.
- Persist the user's theme choice to localStorage on toggle — Save a simple key (e.g., theme='dark'|'light'|'auto') so the preference survives reloads.
- Listen for prefers-color-scheme changes and respect user override rules — Use matchMedia('prefers-color-scheme').addEventListener to update theme when no explicit user choice.
- Handle images and icons for dark mode — Prefer vector icons and theme-aware assets; avoid blind inversion of photos.
- Make SVGs inherit color via currentColor or CSS fill variables — Use inline SVGs or CSS-controlled fills so icons switch automatically with theme tokens.
- Provide dark-mode raster image variants or avoid filter:invert on photos — Use alternate images for photos; filter:invert breaks natural tones and may reduce clarity.
- Theme third-party components and embedded content — Override their CSS variables, inject a theme wrapper, or use their theming APIs where available.
- Verify contrast ratios meet WCAG standards — Aim for AA: 4.5:1 for normal text; use automated tools and manual checks.
- Limit or disable large transitions during theme changes — Avoid heavy animated transitions; honor prefers-reduced-motion to reduce movement.
- Update meta theme-color and PWA tile colors for dark mode — Change <meta name='theme-color'> dynamically so mobile UI chrome matches your theme.
- Test dark mode across browsers, OS, and edge cases — Check incognito, no-JS fallback, high-contrast modes, and different devices for regressions.
Your Stats
🏆
0
Completed
📅
—
Last Done
⏱️
—
Last Time
Completion Rate
Items checked per run
⚡
—
Fastest Run
🔥
0
Streak
🚫
—
Most Skipped Step
🔄
0
Resets
📝 My Notes