postcss-custom-properties 的 preserve: false 是硬性要求;默认双声明会导致ie11静默跳过var()整行而取初始值,仅设preserve: false才删除变量、保留静态值。

postcss-custom-properties 的 preserve: false 是硬性要求
默认配置下,插件只生成双声明:color: #007bff; color: var(--primary);。IE11 遇到 var() 就静默跳过整条规则,最终取继承值或初始值(比如透明背景、黑色文字),样式大面积丢失。只有设 preserve: false 才会真正删掉含 var() 的那行,只保留降级后的静态值。
但注意:如果你同时用了 css-vars-ponyfill,它依赖原始 var() 存在才能运行时替换;此时必须配 preserve: true,但 IE 下就会双失效——PostCSS 没删变量,ponyfill 又因作用域或未定义而跳过。
- Webpack/Vite 项目中,确保该插件在
autoprefixer之前运行,否则可能被后续处理干扰 - 构建后务必检查输出 CSS,搜索
var(--—— 如果还有残留,说明配置没生效或变量不可解析 - 压缩工具如
cssnano若开了discardDuplicates,可能把重复的color声明删掉,要关掉这个选项
:root 下静态常量是唯一可降级的变量来源
PostCSS 插件是编译期工具,看不到 JS 动态设置的变量(如 el.style.setProperty('--color', 'red')),也读不到跨文件定义的内容。所有能被降级的变量,必须满足:
- 定义在
:root(推荐集中管理),不建议放在媒体查询内(如@media (min-width: 768px) { :root { --gap: 16px; } }),因为插件通常无法回溯解析 - 值为静态常量:
--color: red;✅,--size: calc(1rem + 2px);❌,--c: var(--base);❌ - 不能是函数调用、表达式拼接、或依赖其他变量的结果
组件级变量(如 .btn { --bg: blue; })虽可被转换,但作用域受限,不会跨选择器传播,维护成本高,不推荐用于降级主路径。
calc() 里嵌套 var() 必须手动拆解
width: calc(100% - var(--gap)); 在 IE11 中不是 “变量没生效”,而是整个 calc() 表达式被 parser 直接跳过——连数值都不算。PostCSS 默认不处理这种嵌套,因为它无法安全求值。
- 如果
--gap是纯数值(如--gap: 12px;),直接写成width: calc(100% - 12px); - 如果
--gap需动态变化(比如响应式断点不同),就得 JS 注入style属性,或明确放弃 IE11 支持 - 别指望
postcss-calc和postcss-custom-properties链式协作——顺序错或配置漏,结果仍是空值
no-cssvars 类比 @supports 更可靠
@supports (background: var(--x)) 在 IE 中本身不被识别,整条规则被忽略,起不到降级作用。它只能用于现代浏览器的增强逻辑,不能单独作为兼容依据。
真实兜底做法是给 加类:
<script>
if (!CSS.supports('color', 'var(--_)')) document.documentElement.classList.add('no-cssvars');
</script>
再写两套规则:
.btn { background: var(--primary); }.no-cssvars .btn { background: #007bff; }
这个检测用的是 CSS.supports('color', 'var(--_)'),不是 CSS.supports('--_')(后者在 IE 报 TypeError)。关键样式必须双重保障:PostCSS 静态替换 + class 级 fallback,缺一不可。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











