必须同时声明 light 和 dark 媒体查询且在 :root 初始化变量,否则未声明的 var(--bg) 回退为 unset 导致背景透明或继承黑色而白屏/黑屏,Safari 尤其敏感;还需设置 color-scheme: light dark 以确保原生控件适配。

只写 @media (prefers-color-scheme: dark) 会白屏或黑屏,必须同时声明 light 和 dark 分支,且变量得在 :root 里先初始化。
为什么只写 dark 媒体查询就出问题
浏览器不会自动给你兜底——var(--bg) 在未声明时回退为 unset,而 background: unset 可能继承透明或黑色父容器,导致文字看不见、背景消失。Safari 尤其敏感,浅色系统下直接白屏很常见。
-
:root必须先定义所有主题变量的默认值(通常是亮色),比如--bg: #fff、--text: #333 -
@media (prefers-color-scheme: dark)仅用于覆盖,不是首次声明位置 - 漏掉
@media (prefers-color-scheme: light)虽不总报错,但当系统返回no-preference(如某些 Linux 桌面环境)时,变量可能未被赋值,造成不可控渲染
正确写法:变量初始化 + 双媒体查询
顺序不能错:先 :root 定义,再 @media (prefers-color-scheme: light) 显式重置(可选但推荐),最后 @media (prefers-color-scheme: dark) 覆盖暗色值。
:root {
--bg: #fff;
--text: #333;
--border: #e0e0e0;
}
@media (prefers-color-scheme: light) {
:root {
--bg: #fff;
--text: #333;
--border: #e0e0e0;
}
}
@media (prefers-color-scheme: dark) {
:root {
--bg: #1a1a1a;
--text: #e0e0e0;
--border: #333;
}
}
body {
background: var(--bg);
color: var(--text);
}
注意:--bg 和 --BG 是两个不同变量;媒体查询内不能用 !important 覆盖变量,CSS 变量不支持该语法。
立即学习“前端免费学习笔记(深入)”;
color-scheme 声明不能少
光改 body 背景没用,<input>、<select>、滚动条这些原生控件还是亮色边框和白底——它们不读你的 CSS 变量,只看 color-scheme。
- 在
:root或html上加color-scheme: light dark,浏览器才会在深色系统下自动调暗表单边框、滚动条 thumb 等 - 不支持该属性的老浏览器直接忽略,无副作用,放心写
- 别只写
color-scheme: dark,那会强制所有系统都走暗色控件,破坏亮色用户体验
容易踩的兼容性坑
旧版 Safari(12.1 之前)会整条忽略 @media (prefers-color-scheme: dark),连里面的样式都不解析;复合查询更危险。
- 禁止嵌套:
@media (max-width: 768px) and (prefers-color-scheme: dark)在 Safari 12.0 下完全失效 - 构建工具(如 PostCSS 插件、Vite 的 CSS 处理)可能误删或转义
@media块,上线前务必检查生成的 CSS 是否还保留原始规则 - 该媒体查询只在页面加载时读取一次系统偏好,切换系统主题后已打开的页面不会自动更新——需要
matchMedia监听并手动触发重绘(如刷新或 JS 更新 class)
最易被忽略的一点:变量名大小写敏感、声明顺序决定生效结果、color-scheme 不是可有可无的装饰——它直接影响表单控件是否真“暗”了。


















