CSS for Dark Mode

CSS

prefers-color-scheme 这个 Media Query 可以用于检测当前的操作系统是否选择了 Dark Mode。这是一个依然处于初始草案阶段的功能(见 Draft),不过 Safari (12.1) / Chrome (76) / Firefox (67) 的最新版本都已经做了支持。

示例代码如下:

@media (prefers-color-scheme: dark) {
  body {
    background-color: #333;
    color: #fff;
  }
  :not(pre) > code[class*="language-"] {
    background-color: rgba(255,229,100,0.8);
  }
}

下面是一个可编辑的 CSS 代码,可以直接试一试:

注:上面这段代码是可改的,修改后的 CSS 会直接生效。但是由于 contenteditable 的限制,所有代码需要在一行内完成。

除了 dark 之外,prefers-color-scheme 可以接受的属性还有 lightno-preference 两种。其中,light 表示用户选择的是 Light 模式,no-preference 表示用户并没有做选择。

在 JavaScript 中,也可以通过下面的代码来判断当前是否是 Dark Mode:

const ifDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches;

注:从当前的实验结果来看,matchMedia 的结果用 .addListener 注册回调事件并不能生效(Safari 12 测试)。

注:经测试,Safari 13 可以支持 matchMedia 结果 .addListener 的回调。因而,通过 JavaScript 来感知 Dark Mode 的修改,可以通过类似如下的代码完成:

function listenToDarkMode(callback: (isDarkMode: boolean) => void) {
  const matchQueryList = window.matchMedia('(prefers-color-scheme: dark)');
  matchQueryList.addListener(function (event: MediaQueryListEvent) {
    callback(event.matches);
  });
  callback(matchQueryList.matches);
}

如果图片的展示也需要区分,mediaQuery 也可以帮上忙:

<picture>
  <source srcset="mojave-night.jpg" media="(prefers-color-scheme: dark)">
  <img src="mojave-day.jpg">
</picture>