Detecting system theme in JavaScript / CSS / React
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.