近几年,各个主流操作系统都逐渐开始重视暗色模式,从而改善用户在环境光亮低时的阅读体验。随着水果在 iOS 13 与 macOS Mojave 中添加了暗色模式,除了 Linux 以外所有的主流操作系统都已经实现了系统层级的暗色模式。Linux 由于 DE、WM 的种类繁杂暂时没有统一的标准,但目前可以通过暗色 GTK+ 主题、浏览器插件等方式实现“伪全局”暗色模式。既然有了系统层级的适配,浏览器就可以读取暗色模式开关,从而实现网页的自适应。这就是新标准 prefers-color-scheme。

prefers-color-scheme 是什么

W3C 在 2020 年 7 月 31 日发布的 Media Queries Level 5 标准草案 中提到了新的属性 prefers-color-scheme,网页现在可以通过条件规则组来获取浏览器宿系统的暗色模式状态并应用了。也就是说,现在我们可以很简单地实现“暗色模式系统访问的页面是暗色的,亮色模式系统访问的页面是亮色的”。

prefers-color-scheme 怎么用

可以参考 MDN 关于 prefers-color-scheme 的 描述
prefers-color-scheme 有 2 种值:

  • light——浏览器宿系统使用亮色主题的界面,同时也是默认值,浏览器 privacy.resistFingerprinting 被设置为 true 时返回的也将是这个值
  • dark——浏览器宿系统使用暗色主题的界面

还有一个已废弃的值:

  • no-preference——浏览器宿系统使用未知主题的界面,当较旧版本的浏览器在宿系统不支持系统层级的暗色模式时会返回这个值,较旧版本的浏览器 privacy.resistFingerprinting 被设置为 true 时返回的也将是这个值

通过条件规则组就可以作出判断。

CSS

@media (prefers-color-scheme: dark) { // 暗色模式样式 } @media not (prefers-color-scheme: dark) { // 非暗色模式样式 }

JavaScript

只使用 CSS 条件规则很难实现某些需求,我们可以对 window 使用 matchMedia 方法得到的 Media 使用 matches 方法来获取系统暗色模式状态:
if (window.matchMedia(‘prefers-color-scheme: dark’).matches) { // 是暗色模式做什么 } else { // 非暗色模式做什么 }
另外还可以监听系统暗色模式的状态,在系统开关暗色模式时作出反应:
window.matchMedia(‘(prefers-color-scheme: dark)’).addListener(e => { if (e.matches) { // 系统开启暗色模式后做什么 } else { // 系统关闭暗色模式后做什么 } });

兼容性

其实 prefers-color-scheme 也不是什么新东西了,去年水果就已经在 macOS Mojave 上的 Safari 中添加了它,随后各浏览器不断跟进,现在的兼容性还算不错:
image.png