前言

从苹果推出 Night Shift 之后夜间模式开始大面积普及,在光线不好的环境里确实能或者更好的观感,其实这个模式很早就有相似的东西,比如 Windows 里面有高对比度模式这样的主题。当时就试过用很老套的方法在网页上去实现,然后前不久翻文档发现已经有了一个新的 css 属性支持这一特性。

很老套的常规方法

很久以前尝试过的方法,实现方式就是在页面加载时判断当前时间,然后在 body 中加载一个 light / dark 用来标识全局模式,内部的其他需要在夜间模式下切换的样式都会在前面适配 .light / .dark 两种状态;由于做不到自动切换,所以一般会在界面上放一个 切换按钮 手动控制(其实也不是做不到,比如用轮询就可以,但是总感觉不够优雅)。

<head>
<style>
.light .box {
color: #000;
background: #fff;
}
.dark .box {
color: #fff;
background: #000;
}
</style>
</head>

<body class="light">
<button id="toggle">目前是light模式</button>
<div class="box">我在昼夜模式切换时会显示不同的字体颜色和背景色</div>
</body>

<script>
var toggleBtn = document.getElementById('toggle')

function toggleTheme (theme) {
document.body.setAttribute('class', theme)
toggleBtn.innerHTML = '目前是' + theme + '模式'
}

// 18点到凌晨6点设置为夜间模式
var isDark = (new Date).getHours() > 18 || (new Date).getHours() < 6
if (isDark) {
toggleTheme('dark')
}

toggleBtn.addEventListener('click', function(e) {
var currentTheme = document.body.getAttribute('class')
if (currentTheme === 'light') {
toggleTheme('dark')
} else {
toggleTheme('light')
}
})
</script>

用新的css属性实现

说它新,其实也不新了,因为看了一下有浏览器19年就支持了,只是一直没关注到🙄,这才是我想要的优雅方案。

用法上它其实就是一种媒体匹配,跟其他的 @media 语法一模一样,只需要将要改变配色的内容写在里面即可,拥有3种类型值:lightdarkno-preference,最后一个表示没有拿到系统当前的状态。

一般我们直接写好普通模式下的样式,然后对夜间模式的做特殊处理即可:

<head>
<style>
.box {
color: #fff;
background: #000;
}
@media (prefers-color-scheme: dark) {
.box {
color: #fff;
background: #000;
}
}
</style>
</head>

<body>
<div class="box">这是一个自适应昼夜模式的页面</div>
</body>

同时它还支持自适应切换,也就是系统处于什么模式它就会相应的切换,浏览器层面应该是可以检测到系统级事件支持它完成这种操作:

夜间模式

不过夜间模式的匹配在色彩学上还是有不少讲究的,稍微需要一点点设计,这里只做了一点点使用层面的演示,本站已支持主题模式切换,切换设备模式即刻见效。