AsukaSong
AsukaSong

Reputation: 1048

How to detect prefers-color-scheme change in javascript?

I can use window.matchMedia to detect whether user is in dark mode, but how to listen dark mode change event?

Is there any API like:

window.addEventListener('perfers-color-scheme-change', () => {
  // do something
})

Upvotes: 50

Views: 19080

Answers (3)

drussell
drussell

Reputation: 649

In React, a great way to do this is to create a custom hook like so

import React, {useEffect, useState} from 'react';

export const useTheme = () => {
    const initialTheme = darkTheme;
    const [theme, setTheme] = useState(initialTheme);
    useEffect(() => {
        const darkThemeListener = (e) => e.matches && setTheme(themes.dark);
        const lightThemeListener = (e) => e.matches && setTheme(themes.light);
        const mdark = window.matchMedia("(prefers-color-scheme: dark)");
        const mlight = window.matchMedia("(prefers-color-scheme: light)");
        mdark.addEventListener("change", darkThemeListener);
        mlight.addEventListener("change", lightThemeListener);
        return () => {
            // cleanup event listeners
            mdark.removeEventListener("change", darkThemeListener);
            mlight.removeEventListener("change", lightThemeListener);
        };
    }, []);
    return theme;
};

Upvotes: 5

hc_dev
hc_dev

Reputation: 9377

You can add an event-listener with callback on the MediaQueryList returned by Window.matchMedia():

function activateDarkMode() {
  // set style to dark
}

// MediaQueryList
const darkModePreference = window.matchMedia("(prefers-color-scheme: dark)");

// recommended method for newer browsers: specify event-type as first argument
darkModePreference.addEventListener("change", e => e.matches && activateDarkMode());

// deprecated method for backward compatibility
darkModePreference.addListener(e => e.matches && activateDarkMode());

Note: There are two method versions to register an event-listener:

  1. the recommended addEventListener("change", listener)) which allows more fine-grained assignment to event-types
  2. the deprecated addListener(listener)

See also


Thanks to lukaszpolowczyk for pointing out that method addListener(listener) has become deprecated and to AsukaSong for initiating a complete rewrite of this answer.

Upvotes: 63

Kolya_YA
Kolya_YA

Reputation: 431

With initialization setter and 'change' listener.

const colorSchemeQueryList = window.matchMedia('(prefers-color-scheme: dark)');
  
const setColorScheme = e => {
  if (e.matches) {
    // Dark
    console.log('Dark mode')
  } else {
    // Light
    console.log('Light mode')
  }
}
  
setColorScheme(colorSchemeQueryList);
colorSchemeQueryList.addEventListener('change', setColorScheme);

Upvotes: 18

Related Questions