ie11及更早版本完全不解析var(--x)语法,整条css声明被静默丢弃;postcss-custom-properties需设preserve:false才能移除var()并保留降级值,否则旧浏览器仍失效。

IE11 及更早版本根本不会解析 var(--x) 语法,不是“兼容性差”,而是整条 CSS 声明被静默丢弃——连 fallback 值都不走。你看到背景透明、边框消失、布局塌陷,不是代码写错了,是浏览器压根没读那行 CSS。
postcss-custom-properties 必须设 preserve: false
默认配置下,插件只做“追加替换”,比如把 color: var(--primary) 变成 color: #007bff; color: var(--primary);。IE 看到第二行直接跳过,结果还是回退到继承色或 initial(比如 background: initial 是 transparent)。
只有启用 preserve: false,插件才会真正移除 var() 调用,只保留降级后的静态值:
-
preserve: true→ 新浏览器可用变量,旧浏览器仍失效(因为var()还在) -
preserve: false→ 旧浏览器能用,但新浏览器失去动态能力(如主题切换、CSS-in-JS 修改) - 不写该选项 → 等同于
preserve: true,旧浏览器照样白屏
变量定义位置和值必须满足静态可求值
PostCSS 插件在构建时工作,它看不到 JS 动态设置的变量,也读不到跨文件定义的内容。所有能被降级的变量,必须满足:
- 定义和使用在同一 CSS 文件内(或通过
@import明确引入) - 变量声明在
:root最稳妥;局部作用域如.card { --pad: 1rem; }默认不处理,除非配importFrom指向源文件 - 值必须是静态常量:
--color: red;✅,--size: calc(1rem + 2px);❌,--c: var(--base);❌ - Webpack + CSS Modules 项目中,类名哈希会破坏作用域识别,建议全局变量统一收口到
:root
calc() 里套 var() 在 IE11 中彻底不可用
width: calc(100% - var(--gap)) 这种写法,在 IE11 不是 “var() 不生效”,而是整个 calc() 表达式被 parser 直接跳过。PostCSS 插件默认也不处理这种嵌套,因为无法安全求值。
不要指望 postcss-custom-properties + postcss-calc 自动链式替换——顺序错或配置漏,结果还是空值。
- 稳妥做法:把
--gap: 12px这种纯数值变量,直接写成width: calc(100% - 12px) - 如果
gap需动态,就得 JS 注入内联样式,或放弃 IE11 支持 - 别用
postcss-calc试图“先替换再计算”:它只处理已知数值,对未替换的var()无能为力
兜底 class 比 @supports 更可靠
@supports (background: var(--x)) 在 IE11 里会报 TypeError,因为它根本不认识 @supports 规则。不能单独依赖它做降级。
真正有效的兜底是手动加 class:
- 页面加载时用 JS 检测:
if (!CSS.supports('color', 'var(--t)')) document.documentElement.classList.add('no-cssvars'); - CSS 里写两套:
.btn { background: var(--primary); } .no-cssvars .btn { background: #007bff; } - 别用
background: #007bff; background: var(--primary);这种覆盖写法——IE 会把第二行当无效值,然后回退到父级background,结果可能是transparent
构建后必须人工打开产出的 .css 文件,全局搜索 var(--:如果还有残留,说明变量定义位置不对、值含动态表达式、或 PostCSS 插件根本没生效——这个检查步骤容易被跳过,但恰恰是最关键的一环。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











