Javascript & CSS — Toggle dark/light theme based on your user's preferred scheme

This blog focuses on how to switch between the dark and the light theme as per your user's preference.

Javascript & CSS — Toggle dark/light theme based on your user's preferred scheme

After the release of the dark theme in all the major platforms like macOS X, Windows 10, Android, etc. it has become very famous, especially among the developers. People also believe that it helps them reduce eye strain, which is true only if the colors and their contrast are not chosen poorly. Also, it saves battery for some OLED/AMOLED screens.

For the UI/UX developers, it's a new (but optional) challenge to build two separate and equally beautiful designs. Also, it is useful to analyze what is your user's preferred color scheme.

You can also try toggling between these two themes on this blog. This blog (which is using Casper theme by Ghost) also has this feature.

This blog is not focused on whether to use the dark theme in your web app. Instead, it focuses on how to switch between the dark and the light theme as per your user's preference.

How does it work?

It's just a simple media query: prefers-color-scheme

This query has been introduced in the Media Queries Level 5 draft and it can have the following values:

  1. light: The user prefers a page with a light theme. Typically, a light background with the dark fonts.
  2. dark: The user prefers a page with a dark theme. A dark background with relatively lighter fonts.
  3. no-preference: This means the system doesn't know the preference of the user. I generally prefer to display the light theme in this case.

Enabling Dark theme using CSS

There are multiple ways to do this using CSS.

Using media query inside your CSS file:

This is the most straightforward way to implement the dark theme in your app. And if your browser supports the dark theme, it will work for almost all the cases. The example below can be the simplest one to explain this point.

/* style.css */
body {
    background-color: #fafafa;
    color: #222222;

@media(prefers-color-scheme: dark) {
    body {
    	background-color: #222222;
        color: #fafafa;
    <link rel="stylesheet" href="dark.css" media="(prefers-color-scheme: dark)">
    <link rel="stylesheet" href="light.css" media="(prefers-color-scheme: no-preference), (prefers-color-scheme: light)">

Here's the tricky part in this case. If this media query is not supported by the browser, it will load all the CSS. So, you must give preference to one theme for such cases. In the example above, you can see that even if the media query fails, the light theme will override the dark theme.

Then why do we need Javascript?

In some cases, CSS only approach is not sufficient.

For example, if you want to know the user's preferred scheme for analytics. Or you are loading different text/images using Javascript (can be a different API call) and you want a listener for the change in theme. These things can't be handled by CSS.

Check the preferred theme using Javascript:

if (window.matchMedia('prefers-color-scheme: dark').matches) {
  // It's a dark theme...
} else {
  // It's not a dark theme...

Don't forget to check if matchMedia is there in the window object. It might throw an error if it's not supported by the browser.

Listen to the change in theme:

The user can change the theme while accessing your website. The code above can't help detecting the change in theme. To achieve this, we need a listener which listens on the change in preferred theme by the user.

window.matchMedia('(prefers-color-scheme: dark)').addListener(e => {
  if (e.matches) {
    console.log('dark mode is enabled');
  } else {
    console.log('dark mode is disabled');

If you want to learn more about the implementation and the best practices, check out these links:


Browser support

As of now (Feb 2020), the dark mode is supported by all the recent versions of the major browsers. But still, you should check whether it is supported by the browsers of your target users.

If you like this blog and want more blogs like this, please subscribe to this blog.