css变量不响应暗色模式是因为未在@media中重定义变量,必须在:root下先声明再于@media(prefers-color-scheme: dark)内重新赋值,且需确保顺序正确、有fallback、避免被覆盖,并配合color-scheme和class控制。

直接写 @media (prefers-color-scheme: dark) 但变量没变,不是 CSS 写错了,而是变量根本没被重定义、或重定义位置错了、或压根没初始化。
为什么 var(--bg) 在暗色下还是亮色
CSS 变量不响应媒体查询——它只认“最近一次声明”的值。如果 :root 里只写了 --bg: #fff,那无论系统是否切暗色,var(--bg) 都返回 #fff。
- 必须在
@media (prefers-color-scheme: dark)块内,对:root重新赋值同名变量,例如--bg: #121212 - 这个媒体查询块必须放在所有基础
:root声明之后,否则会被后续无条件声明覆盖 - 每个
var()都要带 fallback:background: var(--bg, #ffffff),但别依赖 fallback 切主题——它只是兜底,不会随模式动态变 - 别在媒体查询里定义新变量(如
--bg-dark),浅色环境下读不到,var(--bg-dark)直接失效
@media 规则写了却没生效的常见原因
DevTools 里规则没被划掉 ≠ 它真起了作用。很多情况是规则匹配了,但样式被更高优先级的选择器盖过去了。
- 检查选择器权重:用
.dark body或html.dark body替代单纯body,避免被.theme-light body类覆盖 - 确认媒体查询没嵌套:像
@media (max-width: 768px) { @media (prefers-color-scheme: dark) { ... } }在 Safari 12.1 之前完全无效 - 不能用 JS 动态插入规则:
document.styleSheets[0].insertRule()在部分浏览器静默失败,必须写死在<style></style>或外链 CSS 中 - 确保没有内联样式干扰:
element.style.backgroundColor = 'white'的优先级高于任何外部 CSS,包括媒体查询
第三方组件颜色错乱,光靠 @media 搞不定
Ant Design、MUI、Chakra 这类库通常自己管理主题状态,和你的 @media 规则天然冲突。它们要么忽略你的变量,要么在你设置完后又用自己的逻辑覆盖。
- 禁用库的自动检测(如 MUI 的
colorModeManager或 AntD 的useDarkMode),改由你统一控制data-theme="dark"或class="dark" - Tailwind 用户必须确认
tailwind.config.js中darkMode: 'class'已启用,否则dark:bg-gray-900不会响应class="dark" - 原生控件(
<input>、<select></select>、滚动条)不读 CSS 变量,必须加color-scheme: light dark声明,否则它们永远显示系统亮色 - 自定义组件(如
.stat-card)要单独适配,库不会替你处理非标准类名
旧系统(iOS 12 / Android 9)下 prefers-color-scheme 直接失效
这些环境里 window.matchMedia('(prefers-color-scheme: dark)').matches 永远返回 false,不是你漏写了什么,是浏览器压根没实现。
- 不要只依赖媒体查询做唯一判断,必须 fallback 到
localStorage.getItem('themeMode')或 URL 参数 - JS 初始化时立刻读取并同步设置
document.documentElement.classList.toggle('dark', isDark),而不是等 DOM 加载完再操作 - 用 class 控制比
style.setProperty()更可靠:伪元素、SVG、表单控件基本不响应变量变更,但能响应 class - 切换主题时务必同步
localStorage.setItem('themeMode', 'dark'),否则刷新就还原
最常被忽略的是 color-scheme 声明和变量初始化顺序——没它,原生控件永远亮着;变量没在顶层 :root 先定义,暗色规则就等于白写。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











