How to Support Light and Dark Themes in PWA Using Only CSS
Source: Dev.to
Overview
Web applications now need to support both light and dark modes. Users should be able to choose their preferred appearance, and this can be achieved with pure CSS when browsers support the light-dark() function or the prefers-color-scheme media feature.
Using light-dark() (CSS 4)
If the browser implements the light-dark() function, you can define CSS custom properties that automatically switch values based on the system or browser theme:
/* style.css */
:root {
color-scheme: light dark;
--background: light-dark(white, black);
--color: light-dark(black, white);
}
- The first argument (
white,black) applies to the light theme. - The second argument (
black,white) applies to the dark theme. - Any custom property name can be used; just follow the same
light-dark()syntax.
No additional JavaScript or framework code is required.
Fallback with prefers-color-scheme
For browsers that do not support light-dark() but do support the prefers-color-scheme media query, use a simple media rule:
/* style.css */
:root {
color-scheme: light dark;
--background: white;
--color: black;
}
@media (prefers-color-scheme: dark) {
:root {
--background: black;
--color: white;
}
}
If a browser supports neither light-dark() nor prefers-color-scheme, the CSS will have no effect, and there is no practical fallback.
Limitations
- This approach respects only the system‑wide theme setting (operating system or browser). It does not provide an in‑app toggle for users.
- Older browsers, including all versions of Internet Explorer, lack support for both
light-dark()andprefers-color-scheme, so the theme will not change automatically. - To offer a per‑application theme switch or to update favicons, manifest colors, and other UI elements, additional JavaScript is required.
Extending the Solution
- SCSS Variables – Replace raw color values with SCSS variables for easier maintenance.
- JavaScript Enhancements – Detect the user’s preference, store a manual override, and dynamically update:
- Meta
theme-color - PWA manifest icons
- Any other DOM elements that need to reflect the chosen theme
- Meta
- Framework Integration – While the pure‑CSS method works regardless of framework, you may integrate it into component libraries (e.g., styled‑components) if desired, but it’s not mandatory.
By keeping the CSS snippet above as a baseline and adding JavaScript only where necessary, you achieve full dark‑theme support with minimal complexity.