light-dark() 函数需配合 color-scheme: light dark 声明才生效,仅响应系统 prefers-color-scheme,不支持 js 主题切换。✅ 适合零 js 系统跟随;❌ 不适合手动切换、localstorage 记忆或旧版 safari。

light-dark() 函数必须配合 color-scheme 才能生效
单独写 light-dark(#333, #eee) 不会自动响应系统偏好,浏览器直接忽略该函数值。关键前提是根元素(:root 或 html)必须声明 color-scheme: light dark,否则函数始终返回第一个参数(即浅色值)。这个声明告诉浏览器:本页面支持两种颜色方案,并允许它根据用户系统设置协商最终采用哪一套。
light-dark() 不能用于动态 JS 主题切换场景
该函数只响应操作系统级的 prefers-color-scheme 媒体查询,无法感知你用 document.body.classList.toggle("dark") 手动添加的类。如果你需要用户主动点击切换(而非跟随系统),light-dark() 就不适用——它不是“主题开关”,而是“系统偏好反射器”。
- ✅ 适合:默认跟随系统、无需按钮、追求零 JS 的静态主题适配
- ❌ 不适合:带手动切换按钮、需 localStorage 记住偏好、要兼容旧浏览器(如 Safari
light-dark() 的 fallback 和嵌套限制
函数只接受两个参数,不支持第三个 fallback 值;也不能嵌套使用(如 light-dark(light-dark(...), ...))。更隐蔽的坑是:它不能直接用于 background-image 的渐变色 stops,也不能在 @keyframes 中作为动画属性值——这些地方会解析失败,退回到初始值或触发 CSS 错误。
常见错误现象:border-color: light-dark(#ccc, #333) 在深色模式下仍显示浅灰,往往是因为父容器设置了 color-scheme: light,覆盖了根元素声明,导致协商结果锁定为浅色。
替代方案:用 :root 变量 + class 切换更可控
若你既要系统自动适配,又要保留手动覆盖能力,推荐组合写法:
:root {
color-scheme: light dark;
--text-color: light-dark(#333, #eee);
}
body.dark-manual {
--text-color: #eee;
}
body.light-manual {
--text-color: #333;
}
p { color: var(--text-color); }
这样既利用了 light-dark() 的原生能力,又通过 class 覆盖提供了用户控制权。注意:手动 class 必须比 :root 优先级更高(所以用 body.xxx 而非 :root.xxx),且需用 JavaScript 同步更新 class 与 localStorage。
最易被忽略的一点:light-dark() 是 CSS 层的声明式逻辑,它不触发 JavaScript 事件,也无法被 window.matchMedia("(prefers-color-scheme: dark)").addEventListener 监听变化——你得自己监听媒体查询并同步状态,否则 UI 按钮图标和 localStorage 值会不同步。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











