增加了暗黑模式

用了一段时间 iOS 的 dark mode 感觉良好,特别是夜间看手机不会很刺眼。周末给网站加了暗黑模式功能,检测用户设备对用户切换到暗黑模式,不需要插件,只要一小段 js 和 css 代码即可。

提醒:这里有更好的方法

实现原理

  1. 通过 js 获取当前访问设备的主题色设置模式做判断给 html 页面增加样式;
  2. 利用增加的样式和 css 的自定义属性切换 css 属性值。

利用 js 代码获取当前访问设备的主题色设置模式,并在页面 html 的 body 标签上增加 css 类 dark

if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches{
document.querySelector("body").classList.add("dark")
};

其中,prefers-color-scheme CSS 媒体特性用于检测用户是否有将系统的主题色设置为亮色或者暗色,详情请见 prefers-color-scheme

处理 css 样式:第一步,定义暗黑模式和正常模式下的 css 样式

/* 这里定义暗黑模式下的样式 */
.dark{
--dark-background:#333;
--dark-color:#333;
}
/* root 伪类定义正常模式下的样式 */
:root{
--light-background:1px solid #e5e5e5;
--light-color:1px solid #555;
}

处理 css 样式:第二步,修改暗黑模式下需要调整的 css 样式

这里需要用到 var() 函数的备用值功能来处理正常模式下的样式,否则在正常模式下获取不到样式。

.wrapper{
background:var(--dark-background,var(--light-background));
color:var(--dark-color,#666);
color:#666; /* 此处属性的目的是兼容不支持 css 自定义属性的浏览器 */
}

什么是 css 自定义属性

自定义属性(有时候也被称作 CSS 变量或者级联变量)是由 CSS 作者定义的,它包含的值可以在整个文档中重复使用。

使用 css 自定义属性

css 自定义属性使用起来非常简单和方便,如下:
由自定义属性标记设定值,如: --dark-color: #000;
由 var() 函数来获取值,如: color: var(--dark-color);
以上效果等同于 color:#000;
var() 函数可以定义多个备用值 (fallback value),当给定值未定义时将会用备用值替换,语法为:

var( <custom-property-name> [, <declaration-value> ]? )

例如:

.dark {--dark-color: #333}
.light {-—light-color: #eee}
body {
color: var(--dark-color, —light-color)
}

当 --dark-color 未定义或是无效值时,取 —light-color 。

为了实现暗黑模式的切换,我们可以这样处理:

.dark {—-background-color: #333}
.light {—-background-color: #eee}
body {
background: var(--background-color)
}

如此,就可以在系统切换到深色模式时给 body 加上 dark 类:<body class=“dark”>;当切回浅色模式时用 light 替换掉 dark:<body class=“dark”>

灵活使用 css 自定义属性会来带意想不到的效果。
更多请见:使用 CSS 自定义属性(变量)

浏览器兼容性

本文用到的 CSS 自定义属性和 prefers-color-scheme 可能需要考虑浏览器的兼容性问题,关于浏览器兼容性详情请见各自的文档说明:

  1. prefers-color-scheme
  2. 使用 CSS 自定义属性(变量)

回复 wys 取消回复

评论(9)

  1. 叶开楗 via Chrome 94

    也有用js插件的 哈哈!方便点。

  2. Yan via Chrome 94

    ps 不用cookie有个问题,刷新时会有一个闪烁。

    1. 秩秩斯干

      @Yan 确实是这样 👍👍👍

  3. Yan via Safari 15

    办法不错。我稍微改了一下,时间在22点到6点强制为黑色。

    1. 秩秩斯干

      @Yan 起因是上次在你那看到右下角有个小太阳切换,觉得好,决定弄一下。这个方法也不好变量搞多了影响性能。还是加载单独的样式文件比较好,弄了深色模式才发现比我想象的复杂,颜色不是简单变灰变黑那么简单,还有这里的logo深色模式下直接成另一种风格了。

      1. Yan via Chrome 94

        @秩秩斯干 确实比想象的要复杂,我昨晚就被你“害了”,调了半天,哈哈哈!

        逻辑:
        1、点小太阳时的权限最高。同时写入cookie。
        2、其次以21点到6点为准强制调成黑色。也写入cookie。
        3、最后其余时间参考系统的颜色模式。不写入cookie。

        1. 秩秩斯干

          @Yan 😄,高级啊 👍👍👍

  4. wys via Android

    现在没变过来呢?
    我也想弄一个,像mac里的word,下午一过就自动暗黑背景白色字了。

    1. 秩秩斯干

      @wys 您本地启用深色模式再刷新没变化吗,需要您本地启用深色模式才会切到深色模式。