DEV Community

Cover image for How to Support Light and Dark Themes in PWA Using Only CSS
Federico Moretti
Federico Moretti

Posted on

How to Support Light and Dark Themes in PWA Using Only CSS

Web applications now need to be displayed in two modes: light and dark. There is no way around it, and it must be up to the user to choose which one they prefer. There are several ways to offer this feature, but one in particular is within everyone’s reach. Here’s how to do it using only CSS.

It’s Impossible Not to Support Dark Mode

Although my product colleagues disagree, today dark themes in web applications are just the tip of the iceberg when it comes to basic UX features. Updated browsers do not need to implement major code changes. If they support the light-dark() function, then a CSS change is sufficient.

Otherwise, a more complex solution using JavaScript and other front-end development tools must be implemented. And I will do this too, as I adopted a similar strategy for metadata some time ago. We are still talking about the same feature, namely the media prefers-color-scheme.

This can only accept light and dark values. Thanks to the light-dark() function in CSS, we can set variables that take on the correct values based on the users’ choice. The choice is not made for the individual app, but for the entire operating system or for the browser in use.

How to Implement Dark Mode in CSS

It doesn’t matter which framework you use, or if you don’t use one at all. The only precaution is to integrate the code below into the main CSS file, accessible from any other secondary CSS file (if available). You could use a styled component with some adjustments, but I don’t recommend it.

:root {
  color-scheme: light dark;
  --background: light-dark(white, black);
  --color: light-dark(black, white);
}
Enter fullscreen mode Exit fullscreen mode

Of course, you can use any variables you want instead of --background and --color, as long as you follow the same structure. The first value assigned to the light-dark() function will be valid for the light theme, and the second for the dark theme. No other adjustments are necessary.

The Same Implementation for Older Browsers

If the browser does not support the light-dark() function but supports the prefers-color-scheme media feature, then the same implementation can be used with a minor modification. If it does not support either of these, there is no point in continuing, because the code would have no effect.

:root {
  color-scheme: light dark;
  --background: white;
  --color: black;
}

@media (prefers-color-scheme: dark) {
  :root {
    --background: black;
    --color: white;
  }
}
Enter fullscreen mode Exit fullscreen mode

The same instructions apply to code positioning. Furthermore, whatever you choose, you can always integrate SCSS variables instead of color codes (I used white and black for brevity, but you can use any of the supported formats). In my case, I didn’t want to mix the two things.

Problems and Limitations of This Solution

As I mentioned earlier, this solution does not allow the user to select a choice limited to the web application in use. I will also share how I set up this option, but that is a separate issue. The choice taken into consideration is solely that of the system, whether it has been set at the operating system or browser level.

For this reason, it is not possible to use this solution on older browsers. I mean, it will never work on any version of Internet Explorer… and I know that some people still use it. In the fallback above, I didn’t set the light mode because it’s not necessary: just set the dark mode.

In my daily experience, this approach is sufficient to provide full functionality: I don’t see the point of having the desktop in one mode, the browser in another, and individual applications in yet another. However, since users expect to be able to switch from the app’s user interface, we will have to proceed differently.

The Role of Frameworks in Supporting the Feature

I am familiar with most existing frameworks because my job requires it, but if I could, I would avoid using them. However, in this case, any framework can help add all the pieces that contribute to full dark theme support. Because it’s not just a matter of CSS, as we’ve already seen.

In addition to the theme color set in the metadata, many users now also customize the icon in their favorites and other logos that appear on the desktop. This operation is possible provided that JavaScript code is included that modifies the DOM based on the choices made.

That’s why what I’ve proposed is not enough to meet all potential needs. My idea is to keep this CSS code as a basis (and as a potential fallback). Then, use JavaScript to add the parts that relate to the specific choice for the individual application. Which I will also propose here as soon as possible.

If you like, follow me on Bluesky and/or GitHub for more contents. I enjoy networking.

Top comments (0)