How do I detect dark mode using JavaScript?

Detect Dark Mode in JavaScript and learn how to watch for changes, so you can update your styles accordingly.

For this, we'll need to use the window.matchMedia API.

The window.matchMedia API is a JavaScript utility for checking if the document matches a particular media query.

window.matchMedia will return a MediaQueryList object with a boolean property, matches. This will work with any of your typical media queries, and looks like this for prefers-color-scheme.

window.matchMedia('(prefers-color-scheme: dark)');

First, we have to check if the user has been to our site and a localStorage "theme" item has already been set. Next, we need to check if the user's preference isn't dark mode via prefers-color-scheme. We also need to make sure that the toggle can update the theme after the user's initial preference is set.

Example of code

<!DOCTYPE html>
<html>
  <head>
    <title>How to detect if the User's OS prefers dark mode and change your site with CSS and JS</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <style>
      html.dark {
        background: #000;
        color: #fff;
      }

      html.light {
        background: #fff;
        color: #000;
      }

      [data-color-scheme="dark"] {
        color-scheme: dark;
      }

      [data-color-scheme="light"] {
        color-scheme: light;
      }
    </style>
    <script>
      let prefersDark = matchMedia('(prefers-color-scheme: dark)');
      prefersDark.addEventListener('change', event => loadTheme());

      function setTheme(theme) {
        if (theme == 'auto') {
          localStorage.removeItem('theme');
          loadTheme(null);
        } else {
          localStorage.setItem('theme', theme);
          applyTheme(theme);
        }
      }

      function loadTheme(theme) {
        theme = localStorage.getItem('theme');
        theme ??= (prefersDark.matches) ? 'dark' : 'light';
        applyTheme(theme);
      }

      function applyTheme(theme) {
        document.documentElement.className = theme;
        document.documentElement.setAttribute("data-color-scheme", theme);
      }
      window.setTheme = setTheme;
      loadTheme();
    </script>
  </head>
  <body>
    <input type="button" value="Dark mode" onclick="window.setTheme('dark');">
    <input type="button" value="Light mode" onclick="window.setTheme('light');">
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. In bibendum dui nulla, vitae venenatis nisl placerat vel. In eget efficitur orci. Sed sit amet efficitur augue, a pretium nibh. Nulla pulvinar vel eros eu cursus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. In consequat nisi rutrum, ullamcorper mauris ac, condimentum nisi. Nunc tortor nisl, vulputate sit amet ipsum scelerisque, mattis pretium elit. Nam non sapien facilisis, ullamcorper magna eu, pharetra metus. Ut accumsan ut neque placerat tempus. Mauris posuere urna non nisl euismod, id dignissim nunc tincidunt. Pellentesque at gravida nisi, vitae pulvinar nunc. Nam mi odio, consequat id sollicitudin aliquet, aliquet in neque. Integer bibendum libero pretium, condimentum ante in, dignissim nibh. Praesent viverra lacus luctus, consectetur elit ac, dignissim tortor. Duis pellentesque, nisl sit amet tincidunt ornare, arcu risus ornare dolor, non scelerisque mi libero a velit.</p>
  </body>
</html>