prefers-color-scheme 媒体查询必须独立成块、顶格书写且括号空格规范,不能嵌套或省略符号;它仅运行时动态更新 css 变量,无法操作 dom 或影响 less 编译变量;需显式处理 light/dark/no-preference 三态并兼容旧浏览器。

prefers-color-scheme 媒体查询必须独立成块,不能嵌在样式声明中间
直接写 body { color: white } @media (prefers-color-scheme: dark) { body { color: black } } 会解析失败——CSS 解析器把 @media 当作新规则起点,不是“插在中间的开关”。浏览器会丢弃整个后续块,甚至导致后面所有样式失效。
正确结构只能是:先写默认样式,再用完整 @media 块覆盖。且 @media 必须顶格、独立、带括号和空格:@media (prefers-color-scheme: dark) 少一个空格或冒号都会静默失效。
- 不要写成
@media prefers-color-scheme: dark(漏括号) - 不要写成
@media(prefers-color-scheme:dark)(括号/冒号紧贴) - 不能嵌套在
@supports或其他@media里,例如@media (width >= 768px) { @media (prefers-color-scheme: dark) { ... } }在旧版 Safari 中完全不识别
Less 中无法直接用 @media 注入 class 或触发 JS 行为
@media (prefers-color-scheme: dark) 是纯 CSS 层能力,它只能改样式,不能操作 DOM、不能加 class、不能调 JS 函数。常见错误是想用它配合 Less 变量自动切换主题类:@media (prefers-color-scheme: dark) { html { class: "theme-dark"; } } ——这语法非法,浏览器直接忽略。
如果你需要 JS 主动控制(比如用户点按钮切深色),@media 不参与该流程;它只响应系统偏好变更。两者要分开设计:
- 系统偏好驱动的部分,用
@media (prefers-color-scheme: dark) { :root { --bg: #1e1e1e; } } - 用户手动切换的部分,靠 JS 改
document.documentElement.classList或style.setProperty - 两者共存时,注意 CSS 变量初始化:light 分支也得显式定义
--bg: #fff,否则手动切 dark 后再切回 light,变量可能残留旧值
Less 编译时变量和运行时 CSS 变量必须桥接,不能混用
Less 的 @primary-color 是编译期常量,生成后就固化成 #409eff;而 prefers-color-scheme 是运行时动态判断,它只能作用于 CSS 自定义属性(--primary-color)。所以你不能指望 @media 去修改 Less 变量。
真正可行的路径只有一条:把所有主题相关颜色抽成 CSS 变量,在 Less 中用 ~"var(--primary-color)" 或直接写 var(--primary-color)(现代 Less 支持),再通过 @media 块更新这些变量值:
:root {
--bg: #fff;
--text: #000;
}
@media (prefers-color-scheme: dark) {
:root {
--bg: #1e1e1e;
--text: #e0e0e0;
}
}
- 别把
@media块塞进 Less mixin 里——mixin 展开后仍是静态 CSS,无法响应系统变化 - Webpack 的
less-loader的modifyVars是构建时行为,对@media无影响 - 如果用了 Ant Design 等组件库,确认其主题变量是否已映射为 CSS 变量;否则
@media对它们无效
兼容性兜底和 no-preference 边界情况常被忽略
prefers-color-scheme 在 Chrome 76+、Firefox 67+、Safari 12.1+ 才支持。更关键的是,它返回的值不只是 dark 或 light,还有 no-preference(比如系统未设置、或某些 Linux 桌面环境)。若只写 @media (prefers-color-scheme: dark) 和默认样式,no-preference 会走默认分支,但用户本意可能是“随系统”,结果却固定为 light。
稳妥做法是显式处理三种状态:
- 默认样式对应
no-preference(可设为 light,也可设为中性灰) - 加
@media (prefers-color-scheme: light)显式覆盖 light 场景 - 加
@media (prefers-color-scheme: dark)覆盖 dark 场景 - 老浏览器(如 IE、旧 Safari)完全忽略这些媒体查询,需靠 class 切换方案兜底
最易出问题的不是 dark 模式本身,而是 light 模式下变量未重置、no-preference 被当成 light、以及构建工具误删 @media 块(尤其启用 CSS 压缩或 postcss 插件时)。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











