Implementing Dark Mode in a Web App
16 items · Technical · Medium difficulty · 1 hour
Practical steps to add accessible dark mode to your web app.
-
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.
Printed from TickYouOff — the interactive version tracks your progress and can be shared with others.