每次写暗色模式都要写两套变量?今天 CSS 一行代码把它彻底原生化了
写暗色模式最烦的一步,不是配色,是变量管理——浅色一套、深色一套,两边还要对应上。改一个品牌色要改四个地方,一不小心就有漏网之鱼。
light-dark() 干的就是这件事:一个函数,两个颜色,浏览器自己根据当前主题选一个。
怎么用
两步走:
第一步,在根元素声明支持的主题:
:root {
color-scheme: light dark;
}
第二步,在任何颜色属性里用 light-dark():
body {
background-color: light-dark(#ffffff, #1a1a1a);
color: light-dark(#333333, #eeeeee);
}
浏览器会自动选择——用户系统是浅色就选第一个,是深色就选第二个。
和传统写法比,少了什么
以前的标准做法是每个变量写两遍:
:root {
--bg: #ffffff;
--text: #333333;
}
@media (prefers-color-scheme: dark) {
:root {
--bg: #1a1a1a;
--text: #eeeeee;
}
}
body {
background-color: var(--bg);
color: var(--text);
}
light-dark() 把变量声明和主题对应合到了一起——颜色和它的暗色变体放在一起,不再分散在两个媒体查询里。改一个卡片颜色,改一处就够。
能用在哪
light-dark() 是 CSS Color Module Level 5 的一部分,Chrome 123+、Firefox 120+、Safari 17.5+、Edge 123+ 全部支持。全球覆盖率 88.78%,已经是 Baseline Widely Available 状态。
除了普通颜色,它还能用在:
- 渐变:
background: light-dark(linear-gradient(...), linear-gradient(...)) - 图片(Chrome 150+ 实验性支持):背景图也可以随主题切换
- 配合 color-mix():暗色模式下给颜色加一点蓝调,不只是简单反色
.card {
background-color: light-dark(
var(--gray-100),
color-mix(in oklch, var(--gray-900) 90%, var(--blue-900))
);
}
和 prefers-color-scheme 怎么选
prefers-color-scheme 是媒体查询,写在 CSS 里只读系统偏好,用户手动切换主题它管不了。
light-dark() 依赖 color-scheme 属性,而这个属性可以通过 JS 动态修改——用户点一个切换按钮,document.documentElement.style.colorScheme = dark,所有 light-dark() 的颜色自动切过去,不需要改任何变量值。
两者不是替代关系,而是分工:color-scheme 控制「当前是哪个主题」,light-dark() 在这个主题下选颜色。
防闪屏的坑
如果你的站允许用户手动选主题,要加一段阻塞渲染的 JS 读 localStorage,防止页面先按系统主题闪一下再切过去:
<script>
const saved = localStorage.getItem(color-scheme);
if (saved) document.documentElement.style.colorScheme = saved;
</script>
这段脚本要放在 <head> 里,不带 async,阻塞渲染就开始执行。
三步下一步
- 搜你项目里所有
@media (prefers-color-scheme——看看有没有两套变量的地方可以用 light-dark() 合并 - 加
color-scheme: light dark到:root——这是让浏览器知道「我这个页面支持暗色的」 - 把手动的暗色切换改成改
color-scheme属性——所有 light-dark() 的颜色自动跟过来
这个函数的价值不只是少写代码,是把「主题」从变量管理的泥潭里抽出来,变成一个单一的状态。
评论区
登录后可评论。