Detecting system theme in JavaScript / CSS / React

Kacper Kula
hypersphere
Published in
3 min readAug 12, 2020

Detect system theme using prefers-color-scheme and matchMedia.

You can also watch the content of this article on my YouTube channel:

The dark themes become more and more popular. With the introduction of the dark system variants in Android 9+, macOS Mojave 10.14, and iOS 13, more and more apps and websites start to provide a dark version of their interface. Some offer an option to switch between the versions but it is also possible to detect the theme using CSS or JavaScript. In the following tutorial, I will show how to use these (depending on your needs) and also how to use it with React framework.

Detecting theme in CSS

To detect a dark theme in CSS we can use prefers-color-scheme media feature. Using it we can target either a light or a dark theme that the user has selected for their system.

More information about browser support for prefers-color-scheme can be found on Can I Use website.

Detecting theme in JS

To detect light or dark theme in JavaScript we can use matchMedia function that allows checking programmatically whether a CSS media query has been fulfilled or not.

Using this code snippet we can easily detect what theme the user has set. Note that the code checks the system theme only once and does not react to the dynamic changes of the theme (either manual but the theme might also change automatically depending on a time of the day). If we want to provide the best user experience, we should react to the change and switch our layout accordingly. Fortunately, MediaQueryList object (which is a result of matchMedia call) has a .addListener method which allows us to provide a calback which is exectued every time the media query result changes.

More information about browser support for matchMedia can be found on Can I Use website.

Detecting theme in React

In React (> 16.8) we can create custom hook that will indicate whether the theme is set to dark or not.

We can then use it in any component in the following way:

Debugging color schemes

When you develop a dark theme for your page you might want to switch back and forth between light and dark variant to check how your page renders. It might be quite time consuming to switch it on the system level — the whole procedure might get quite tedious. Fortunately, Safari, Chrome and Firefox allow for emulating the prefers-color-scheme value in their Developer Tools.

Emulating prefers-color-scheme in Chrome

In Chrome the option can be found in a Rendering tab which is accessible from the additional menu on the top right, under More Tools.

Emulating prefers-color-scheme in Safari

In Safari the Web Inspector includes a button to toggle dark or light mode.

Emulating prefers-color-scheme in Firefox

In Firefox theme can be changed using about:config tab. All we need to do is to add a new property ui.systemUsesDarkTheme of type Number. Value of 1 will set the Firefox to dark theme.

Testing dark mode in Cypress

You can also change theme of the browser in the Cypress tests. Thanks to that we can test how the page behaves in both light and dark variant and for example perform accessibility color test. For more details on that I recommend checking brilliant article Test Your Web App in Dark Mode published on Cypress Blog.

--

--