Article Logo Go Back

Dark Mode: OS Level Control In Your CSS

AvatarJul 5, 20193 minsTim Ellenberger

🔥 Demo First 🔥

Default light/dark mode mirrors your operating system

Toggle Mode

You know what really grinds my gears? Explicitly setting my OS to dark mode, going to a website that clearly has a dark mode, and still getting blasted in the retinas by all the bright shades of white.

The only reasonable default mode for the web apps that have them, should be the user's system preference!

Luckily the new media query @media(prefers-color-scheme: dark) is gaining browser support to solve this exact problem.

stylestheme.csscss
1/* The browser supports prefers-color-scheme,2but cannot find a light/dark preference */3@media (prefers-color-scheme: no-preference) {4  background: black;5  color: white;6}7
8/* Use dark mode */9@media (prefers-color-scheme: dark) {10  background: black;11  color: white;12}13
14/* Use light mode */15@media (prefers-color-scheme: light) {16  background: white;17  color: black;18}

Use the Window.matchMedia() function to retrieve this setting programatically in Javascript.

consolejs
1// true if the browser supports prefers-color-scheme2window.matchMedia("(prefers-color-scheme)").matches3
4// true if there is a system level dark mode preference5window.matchMedia("(prefers-color-scheme: dark)").matches

In React you could check for this preference fairly easily, then update your app theme dynamically... and responsibly!

componentsDarkModeReporter.jsjsx
1import React from 'react';2
3class DarkModeReporter extends React.Component {4  state = {5    supportsColorScheme: false,6    isDarkMode: false,7    isLightMode: false8  };9
10  componentDidMount() {11    const supportsColorScheme = window.matchMedia('(prefers-color-scheme)')12      .matches;13    const isDarkMode = window.matchMedia('(prefers-color-scheme: dark)')14      .matches;15    const isLightMode = window.matchMedia('(prefers-color-scheme: light)')16      .matches;17
18    this.setState({ supportsColorScheme, isDarkMode, isLightMode });19  }20
21  render() {22    const { supportsColorScheme, isDarkMode, isLightMode } = this.state;23
24    if (supportsColorScheme) {25      if (isDarkMode) return <>Your system is in dark mode!</>;26      if (isLightMode) return <>Your system is in light mode!</>;27
28      // The browser supports light/dark mode but can't infer anything from the system29      return <>Your system light/dark mode preference is unset!</>;30    }31
32    // The browser doesn't support light/dark mode33    return <>Your browser doesn&apos;t support dark mode!</>;34  }35}36
37export default DarkModeReporter;

For my take on implementing dynamic app themes in React with Styled-Components, check out my post dynamic-theming-with-styled-components-and-nextjs.


Edit Post

Bug?Edit Post