January 7 ~ 3 min

How do you detect if a user of your website has a preference for light or dark theme? Or maybe has not chosen at all?

We will look at a few ways how to detect and handle dark modes in 2020:

Photo by davisco on Unsplash

Pure CSS

First lets have a look how we can do this using only CSS. There is a new css media query that is supported by almost any browser right now.

prefers-color-theme

Example Time

.box { background: #eee; } @media (prefers-color-scheme: dark) { .box { background: #000; } } @media (prefers-color-scheme: light) { .box { background: #fff; } }

Just like we use media queries for device width we can easily target specific CSS in case the user has a specific preference.

For completeness, if the user has no preference you can use the media query @media (prefers-color-scheme: no-preference) .

JS

Simple

So how do we do the same thing in JS? There is a little helper called window.matchMedia (also widely supported) wich takes a media query and tells us if the media query is true of false.

Example

const isDark = window.matchMedia('(prefers-color-scheme: dark)') isDark.matched // true or false

That simple.

Reactive

If we want to go reactive, the matchMedia function also allows us to set a listener, so every time the setting changes, we get notified and can act accordingly.

Example

const isDark = window.matchMedia('(prefers-color-scheme: dark)') isDark.addListener((event: MediaQueryListEvent) => { event.matches // true or false })

React

And of course react. We love it, we use it. So I made a little library because all the libs I found for react did not include typescript typing!! 🤕

Of course it comes with hooks 🎣.

yarn add use-light-switch

useLightSwitch()

This is the basic usage.

import { Mode, useLightSwitch } from 'use-light-switch' const Simple: React.FC = () => { const mode = useLightSwitch() if (mode === Mode.Dark) ... return ... }

useModeSelector()

This is the more useful one IMO.