css变量不能用于@media条件,因媒体查询匹配发生在变量求值前,属规范硬限制;正确做法是在@media内通过:root重设变量值,而非尝试在条件中直接引用var()。

CSS变量(var(--name))不能出现在 @media 条件表达式里,这不是浏览器bug,而是CSS规范的硬性限制——解析阶段就跳过整条规则,且不报错。
为什么 @media (max-width: var(--sm)) 会静默失效
CSS媒体查询的匹配发生在样式计算之前,而 var() 的求值依赖于层叠、继承和作用域解析,这两步根本不在同一处理流程中。浏览器在读到 var(--sm) 时,直接判定为非法值,整条 @media 规则被忽略。DevTools 中该规则显示为灰色,控制台也看不到任何提示。
常见误判包括:
- 以为加 fallback(如
var(--sm, 768px))能绕过语法校验——实际连解析都失败 - 以为预处理器变量(Sass
$sm)等同于 CSS 变量——前者是编译期文本替换,后者是运行时计算 - 把
:root中已定义的值当成“可穿透”,但媒体查询条件根本不参与变量作用域链
如何安全复用断点值:必须重设 :root,而非“覆盖”变量
正确做法是在每个媒体查询块内,对 :root 显式重新声明变量。这不是覆盖,而是在新匹配上下文中建立新的层叠优先级。
示例:
:root {
--bp-sm: 480px;
--bp-md: 768px;
}
<p>@media (max-width: 768px) {
:root {
--gap: 8px;
--font-size-base: 14px;
}
}</p><p>/<em> ✅ 这些样式能读取到新值 </em>/
.card {
gap: var(--gap);
font-size: var(--font-size-base);
}</p>
关键点:
- 必须写
:root,不能省略或换成html或其他选择器 - 必须有顶层
:root声明,否则小屏下变量未定义,无 fallback - 所有依赖这些变量的样式,要么写在该
@media内部,要么确保继承链完整(如子元素从body继承)
替代方案对比:哪些能用,哪些只是幻觉
有些方案看似“绕过限制”,实则各有边界:
-
clamp()/calc()在属性值中可用,但不能用于媒体查询条件本身(如@media (min-width: calc(var(--bp-md) - 1px))依然非法) - JS 动态注入
<style></style>是可行的,但需手动监听resize,且无法响应prefers-color-scheme等系统级变化 - 构建时注入(如 PostCSS 插件)本质是字符串替换,属于预处理,不是原生 CSS 行为
真正可靠的只有 @media { :root { ... } } 这一种模式——它不挑战规范,只利用层叠规则,在匹配时触发变量重计算。
容易被忽略的是:媒体查询中重设的变量,只影响其内部及后代元素;如果某个组件用了 .card { --text-color: #333; },那它不会影响其他同名类的 --text-color 值,作用域仅限于该选择器及其子树。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











