CSS变量(var())不能在@media中作为断点值使用,因媒体查询解析早于变量求值,且规范要求媒体特性必须为字面量;预处理器变量(如Sass)或@custom-media是可靠替代方案。

CSS变量(var())不能在@media条件中作为断点值使用,这是规范层面的硬性限制,不是浏览器bug或版本问题。你写的@media (min-width: var(--breakpoint-md))会被所有主流浏览器(Chrome、Firefox、Safari、Edge)静默忽略——DevTools里整条规则变灰,不报错,也不生效。
为什么var()在@media里完全无效
CSS媒体查询的解析发生在样式计算早期,此时var()引用的自定义属性尚未求值;而规范明确要求媒体特性值必须是字面量(如768px),不能是运行时表达式。这不是“还没支持”,而是设计使然:变量属于级联层,媒体查询属于条件层,二者在CSS引擎中走不同通路。
- 哪怕
:root里已声明--breakpoint-md: 768px,也穿不过去 -
calc()、clamp()、单位换算(em/rem)同样无效 -
var(--x, 768px)的默认值机制在此场景不触发——变量已声明,只是不被解析
预处理器变量才是真正的断点复用方案
Sass/Less/Stylus这类工具在编译阶段就把变量展开为纯CSS字面量,生成的@media (min-width: 768px)是合法且可执行的。这才是目前最稳定、零运行时开销、全浏览器兼容的解法。
- Sass写法示例:
:root {<br> --spacing-sm: 4px;<br>}<br><br>$breakpoint-md: 768px;<br><br>@media (min-width: $breakpoint-md) {<br> .card {<br> padding: var(--spacing-sm);<br> }<br>} - 变量名建议统一前缀,如
$bp-md或$breakpoint-md,避免和CSS变量名混淆 - 不要混用:别在Sass里
@import一个含var()的CSS文件再试图取值——Sass无法读取运行时CSS变量
PostCSS插件能模拟但有前提
像postcss-custom-properties或postcss-custom-media可在构建时将var(--bp-md)替换成实际值,但仅限变量值为静态常量(不能含calc()或嵌套var())。
Miller (mlr) 是一个命令行工具,用于查询、整形和重新格式化名称索引数据,如 CSV、TSV、JSON 和 JSON Lines。它将 awk、sed、cut、join 和 sort 的功能整合到一个专为结构化数据处理而构建的单一工具中。
立即学习“前端免费学习笔记(深入)”;
- 有效:
--bp-md: 768px→ 替换成功 - 无效:
--bp-md: calc(100vw - 200px)→ 插件无法求值,保留原样,@media仍失效 - 需确认构建配置已启用对应插件,且执行顺序在
postcss-preset-env之前
别被@custom-media误导——它不是CSS变量方案
@custom-media --md-up (min-width: 768px)本质是媒体查询别名,不依赖任何变量。它和var()无关,也不能动态改值。
- Safari原生支持;Chrome/Firefox需PostCSS转译(如
postcss-custom-media) - 写
@custom-media --md-up (min-width: var(--bp-md))仍是非法的,会报语法错误 - 它的价值是语义化复用,比如多处写
@media (--md-up),但底层断点值仍是硬编码
真正容易被忽略的是:很多人把Sass变量和CSS变量放在同一份文件里管理,结果改了$breakpoint-md却忘了同步更新--breakpoint-md,导致JS读取断点或伪元素输出时拿到旧值。断点逻辑应该只有一份源头,要么全交给预处理器,要么全交给构建时注入——混用等于自建陷阱。

















