浅谈网站darkmode
前言
为什么(信息流)网站需要暗黑模式?道之所现,白天之后是黑夜。暗黑模式的背后目的是对眼睛,视力的一种保护措施。是网站一种提升用户体验的措施。那么如何实现一个信息流网站的暗黑模式呢?这里有两种思路。
正文
首先,我们需要知道一个知识点prefers-color-scheme
,下面的两种思路都会用到该特性。
prefers-color-scheme CSS 媒体特性用于检测用户是否有将系统的主题色设置为亮色或者暗色。
一般有如下用法:
body {
color: black;
background: white;
}
@media (prefers-color-scheme: dark) {
body {
color: white;
background: black;
}
}
或者
window.matchMedia('(prefers-color-scheme: dark)').addListener((e) => {
if (e.matches) {
// doSomething()
}
})
网站应用暗黑模式的一般表现是将字体、背景色互换,比如将黑字白底换为白字黑体,但对于非字体元素(图标,图片)需要另外的技术加持。
一、root css variables
第一种思路是配合css的变量--variables
特性来实现暗黑模式在网站上的切换。在通过相关途径(prefers-color-scheme: dark
,时间戳,用户代理点击操作)触发暗黑模式的动作后,通过在根元素的style
属性上通过setProperty
方法实时切换相关css变量的值,然后在之后的css样式中,关键属性(字体,背景色)通过之前的css变量来设置。
再来说说这种思路的优缺点,优点是页面元素是干净的,没有添加额外的遮罩层元素;缺点是后续的css样式关键属性的值必须用之前设置的css变量,关联性很强,其次,基本上只能设置字体,背景色的属性值。对于非文本元素不起作用。
这种思路Github上有相关的模块:darken实现的功能非常完备,推荐使用。
二、mix-blend-mode: difference
第二种思路是使用css属性mix-blend-mode: difference
来实现。
mix-blend-mode CSS 属性描述了元素的内容应该与元素的直系父元素的内容和元素的背景如何混合。
mix-blend-mode: normal; //正常
mix-blend-mode: multiply; //正片叠底
mix-blend-mode: screen; //滤色
mix-blend-mode: overlay; //叠加
mix-blend-mode: darken; //变暗
mix-blend-mode: lighten; //变亮
mix-blend-mode: color-dodge; //颜色减淡
mix-blend-mode: color-burn; //颜色加深
mix-blend-mode: hard-light; //强光
mix-blend-mode: soft-light; //柔光
mix-blend-mode: difference; //差值
mix-blend-mode: exclusion; //排除
mix-blend-mode: hue; //色相
mix-blend-mode: saturation; //饱和度
mix-blend-mode: color; //颜色
mix-blend-mode: luminosity; //亮度
mix-blend-mode: initial; //初始
mix-blend-mode: inherit; //继承
mix-blend-mode: unset; //复原
具体思路是:在网页最上层添加一个页面大小的遮罩层,背景色为暗黑,并设置mix-blend-mode
的值为difference
,在触发网站暗黑模式时,启用该遮罩层。这样,用户代理看到的页面就是原先页面与暗黑背景做差值之后的颜色了。需要注意的是,该遮罩层需要设置css属性:pointer-events: none
,以便于页面触摸事件穿透该遮罩层从而正确触发到对应的页面元素上。
该思路的优缺点是:优点,对页面css文件友好,不需要编写相关的css变量的值,而且对非文本元素亦起作用;缺点是页面最上层必须有一个遮罩层,页面元素不够纯净。
这种思路Github上亦有相关的模块:Darkmode.js,推荐使用。