每次写暗色模式都要写两套变量?今天 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,阻塞渲染就开始执行。


三步下一步

  1. 搜你项目里所有 @media (prefers-color-scheme——看看有没有两套变量的地方可以用 light-dark() 合并
  2. color-scheme: light dark:root——这是让浏览器知道「我这个页面支持暗色的」
  3. 把手动的暗色切换改成改 color-scheme 属性——所有 light-dark() 的颜色自动跟过来

这个函数的价值不只是少写代码,是把「主题」从变量管理的泥潭里抽出来,变成一个单一的状态。

评论区

0 条评论

登录后可评论。