Dark Mode Implementation
Implementing theme switching with CSS custom properties, system preference detection, and persistence
You are an AI agent that implements theme switching correctly. You use CSS custom properties for theming, detect system preferences, persist user choices, prevent flash of wrong theme, and ensure all visual elements adapt properly including images and icons.
## Key Points
- Define all colors as CSS custom properties on `:root` or a theme class.
- Switch themes by changing the values of these properties.
- Organize properties semantically: `--color-background`, `--color-text-primary`, not `--white`, `--black`.
- Include properties for surfaces, borders, shadows, and interactive states.
- Use a naming convention that describes purpose, not appearance.
- Use the `prefers-color-scheme` media query to detect the OS setting.
- In CSS: `@media (prefers-color-scheme: dark) { ... }`.
- In JavaScript: `window.matchMedia('(prefers-color-scheme: dark)')`.
- Listen for changes with `matchMedia.addEventListener('change', callback)`.
- Use the system preference as the default when no user preference is stored.
- Store the user's theme preference in localStorage.
- Check localStorage before rendering to apply the correct theme immediately.skilldb get autonomous-agent-skills/dark-mode-implementationFull skill: 98 linesDark Mode Implementation
You are an AI agent that implements theme switching correctly. You use CSS custom properties for theming, detect system preferences, persist user choices, prevent flash of wrong theme, and ensure all visual elements adapt properly including images and icons.
Philosophy
Dark mode is not just inverting colors. It is a complete design system concern that touches every visual element in the application. A proper implementation respects user preferences, transitions smoothly, persists across sessions, and never flashes the wrong theme on load. It must work from the CSS level to the image level, with every component aware of the current theme.
Techniques
Use CSS Custom Properties for Theming
- Define all colors as CSS custom properties on
:rootor a theme class. - Switch themes by changing the values of these properties.
- Organize properties semantically:
--color-background,--color-text-primary, not--white,--black. - Include properties for surfaces, borders, shadows, and interactive states.
- Use a naming convention that describes purpose, not appearance.
:root {
--color-bg-primary: #ffffff;
--color-text-primary: #1a1a1a;
--color-border: #e0e0e0;
}
[data-theme="dark"] {
--color-bg-primary: #1a1a1a;
--color-text-primary: #e0e0e0;
--color-border: #333333;
}
Detect System Preferences
- Use the
prefers-color-schememedia query to detect the OS setting. - In CSS:
@media (prefers-color-scheme: dark) { ... }. - In JavaScript:
window.matchMedia('(prefers-color-scheme: dark)'). - Listen for changes with
matchMedia.addEventListener('change', callback). - Use the system preference as the default when no user preference is stored.
Persist Theme Choice
- Store the user's theme preference in localStorage.
- Check localStorage before rendering to apply the correct theme immediately.
- Provide three options: Light, Dark, System (follow OS preference).
- Sync the preference across tabs using the
storageevent. - Fall back to system preference when no stored preference exists.
Prevent Flash of Wrong Theme
- Apply the theme in a blocking script in the
<head>before any rendering. - Read localStorage synchronously and set the theme attribute on
<html>immediately. - Do not rely on React/framework hydration to set the theme, as it happens too late.
- For server-rendered pages, use cookies to send the theme preference with the request.
- This script must be inline, not in an external file that requires a network request.
Adapt Images and Icons for Themes
- Use
filter: invert(1)for simple icon color inversion. - Provide separate image assets for light and dark themes when inversion is not sufficient.
- Use
<picture>with<source media="(prefers-color-scheme: dark)">for theme-aware images. - SVG icons should use
currentColorto inherit the text color. - Adjust image brightness and contrast in dark mode to reduce eye strain.
Implement Smooth Theme Transitions
- Add a CSS transition on color properties:
transition: color 0.2s, background-color 0.2s. - Apply the transition class temporarily during theme switch, then remove it.
- Do not apply transitions on page load to prevent initial animation.
- Keep transitions short (150-200ms) to feel responsive.
- Transition only color-related properties to avoid layout thrashing.
Handle Component-Level Theme Awareness
- Third-party components may need explicit theme configuration.
- Code syntax highlighting themes must switch with the application theme.
- Charts and data visualizations need theme-aware color palettes.
- Map and embed components may have their own theme APIs.
- Test every component in both themes to catch hardcoded colors.
Best Practices
- Design the dark theme intentionally, not by just inverting the light theme.
- Use slightly lower contrast in dark mode to reduce eye strain (not pure white on pure black).
- Reduce shadow intensity in dark mode; use lighter borders or subtle glows instead.
- Test both themes at every stage of development, not as an afterthought.
- Ensure sufficient contrast ratios (WCAG AA: 4.5:1 for text) in both themes.
- Include the theme toggle in an easily accessible location.
- Test the theme toggle rapidly to verify transitions are smooth and state is correct.
Anti-Patterns
- Hardcoded colors: Using
color: #333instead ofcolor: var(--color-text-primary)throughout the codebase. - Flash of light theme: Page loads in light mode and then switches to dark, causing a white flash.
- Forgotten components: Most of the app supports dark mode, but some pages or modals do not.
- Pure black backgrounds: Using
#000000for dark mode backgrounds, which creates excessive contrast. - Opacity for darkening: Using opacity to darken elements, which also makes them transparent.
- Lost preference: User sets dark mode, refreshes, and sees light mode briefly before it switches.
- No system option: Forcing users to manually toggle instead of following their OS preference.
- Invisible elements: Icons or borders that disappear against the dark background because they were designed only for light mode.
Install this skill directly: skilldb add autonomous-agent-skills
Related Skills
Data Extraction and Transformation
Techniques for extracting, parsing, cleaning, and transforming data across formats like CSV, JSON, XML, and more, including handling malformed input and large files.
Data Validation Patterns
Validating data at system boundaries — schema validation, input sanitization, error message design, and choosing between fail-fast and collect-all-errors strategies.
Database Operations
Safe database interaction patterns including SQL query construction, migration writing, transaction handling, and read/write operation safety.
Dead Code Cleanup
Identifying and safely removing dead code during modifications without breaking hidden dependencies or dynamic references
Debugging Strategies
Systematic approaches to finding and fixing bugs — hypothesis-driven debugging, bisection, stack trace reading, issue reproduction, variable isolation, log analysis, and avoiding shotgun debugging.
Dependency Analysis
Understanding and managing project dependencies — reading manifest files, version conflict resolution, transitive dependency awareness, security audits, minimal dependency philosophy, and lock file handling.