CSS变量不能用于@media条件,因其求值阶段与媒体查询匹配阶段不兼容;正确做法是在@media块内显式重设:root或对应选择器的变量。

var() 不能出现在 @media 条件里,这是 CSS 规范硬性限制,不是 bug,也永远不会支持。你写 @media (min-width: var(--sm)),浏览器直接跳过整条规则,DevTools 显示为灰色,控制台零提示——它连语法校验都没过。
为什么 @media (max-width: var(--bp-md)) 静默失效
媒体查询匹配发生在样式计算之前,而 var() 求值依赖继承、层叠和作用域解析,两者根本不在同一处理阶段。浏览器看到 var(--bp-md) 就判定为非法值,整条规则被丢弃。@media (min-width: var(--sm, 768px)) 同样无效——fallback 不参与语法校验。
JS 修改 --bp-md 后媒体查询不重新匹配
媒体查询只响应视口变化(如 resize),不响应 CSS 变量变更。即使你用 document.documentElement.style.setProperty('--bp-md', '900px'),已匹配的媒体查询不会重触发,也不会导致样式重算。
- 变量变更后,依赖它的属性(如
color: var(--bp-md))不会自动更新,除非触发强制重绘(例如修改transform或 class) -
getComputedStyle(document.documentElement).getPropertyValue('--bp-md')返回新值,但该值对媒体查询无意义 - 别指望用 JS 动态改断点来“驱动”响应式逻辑——这设计上就不成立
正确做法:在 @media 块内重设 :root 变量
变量不能驱动媒体查询,但媒体查询可以重设变量。唯一合法路径是:先在顶层 :root 声明默认值,再在每个匹配的媒体查询块中对 :root 重新赋值。
- 必须显式写
:root,不能省略或换成html或其他选择器 - 必须有顶层声明,否则未匹配媒体查询时变量未定义,
var(--gap, 12px)的 fallback 才会生效,但后续缩放也不会刷新已计算样式 - 示例:
@media (max-width: 768px) { :root { --gap: 8px; --font-size-base: 14px; } } - 所有依赖这些变量的样式,要么写在该
@media内部,要么确保继承链完整(如子元素从body继承)
组件级变量别指望 :root 全局覆盖
你在 .card 里定义了 --text-color,又在 @media (prefers-color-scheme: dark) 中对 :root 改 --text-color,那 .card 内的 var(--text-color) 依然读不到——因为它的作用域是 .card 自身,不是 :root。
立即学习“前端免费学习笔记(深入)”;
- 媒体查询中重定义变量,必须作用于同一选择器层级:
@media (dark) { .card { --text-color: #f0f0f0; } } - 别把所有变量都堆在
:root,否则一个--primary变动会意外影响所有组件 - 组件级变量应带命名空间,如
--card-text-color,避免跨容器污染 -
--color: unset会让继承查找终止,子元素拿不到任何值,只能靠 fallback
:root 变量,只影响其内部及后代元素;如果某个组件用了 .card { --text-color: #333; },那它压根不参与 :root 的继承链——你得在对应选择器上重设,而不是幻想“全局覆盖”。


















