IE11会静默丢弃含var(--x)的整条CSS声明,必须显式配置postcss-custom-properties并设preserve:false,否则变量无法降级;变量须定义在:root且为静态常量,calc()嵌套var()等动态场景不可降级。

必须显式配置 postcss-custom-properties 并设 preserve: false,否则 IE11 会静默丢弃整条声明,不是“不生效”,而是压根没读。
为什么 var(--x) 在 IE11 里直接白屏
IE11 及更早版本的 CSS 解析器遇到 var(--x) 语法,不会尝试 fallback,也不会报错,而是整条规则跳过。比如:
button { background-color: var(--primary); color: #fff; }IE11 实际只看到 color: #fff;,background-color 声明被忽略,结果按钮背景透明、文字叠在底色上——这不是样式写错了,是浏览器根本没解析那行。
常见误判点:
立即学习“前端免费学习笔记(深入)”;
- 以为加了 fallback 就安全:写成
background-color: #007bff; background-color: var(--primary);不够,因为默认插件只“追加”第二行,IE 仍会跳过它 - 依赖
@supports检测:IE 全系不认识@supports语法,规则块直接被忽略,控制台无报错但样式全失 - 变量定义在 JS 里:
document.documentElement.style.setProperty('--c', 'red')—— PostCSS 构建时完全看不到,降级无效
postcss-custom-properties 的关键配置项
这个插件不是开箱即用,必须手动配对才能真正产出 IE 友好代码:
-
preserve: false是硬性要求:它让插件删掉所有含var()的声明,只保留降级后的静态值。不写或设为true,等于没配 - 变量必须定义在
:root下,且值为静态常量:--primary: #007bff;✅,--gap: calc(1rem + 4px);❌(calc()嵌套var()无法安全求值) - 跨文件定义需显式
@import:如果变量在vars.css里,主样式里必须@import 'vars.css';,否则插件找不到定义 - Webpack/Vite 中注意插件顺序:
postcss-custom-properties必须在autoprefixer之前,否则 autoprefixer 可能覆盖或干扰变量替换
构建后必须人工验证的三个地方
跑完构建不能只信文档,得翻输出 CSS 文件确认:
- 全局搜索
var(--:如果还有残留,说明变量未定义、作用域不对,或插件根本没生效 - 检查重复声明是否被压缩工具删掉:如果用了
cssnano,要关掉discardDuplicates,否则像color: #007bff; color: var(--c);这种会被精简成一行,IE 又失效 - 对比开发版和构建版的类名:Webpack + CSS Modules 项目中,哈希类名可能破坏作用域识别,建议全局变量统一收口到
:root,避免组件级.btn { --bg: red; }这类写法
仅靠 PostCSS 降级不够的边界情况
PostCSS 是编译期工具,它解决不了运行时问题:
-
width: calc(100% - var(--gap)):IE11 整个calc()表达式被跳过,不是 gap 不生效,是整条 width 规则消失。稳妥做法是直接写死width: calc(100% - 12px) - 主题切换依赖 JS 动态 setProperty:旧浏览器既不支持
var(),也不支持setPropertyAPI,此时必须搭配css-vars-ponyfill这类运行时方案,且要确保 ponyfill 的初始化早于样式加载 -
@supports not (background: var(--x))包裹的降级样式:IE 不认识@supports,这块规则直接被忽略,必须额外加 class 兜底,比如给加no-cssvars类,再写.no-cssvars .btn { background: #007bff; }
最易被忽略的一点:变量降级只发生在构建阶段,它不感知环境、不判断 UA、不运行 JS。你写的每个 var() 能不能被替掉,只取决于它在源码里是不是一个“静态可求值的常量”。其他一切,都得靠人来补。


















