ie11及更早版本静默丢弃var(--x)整条声明,必须用postcss-custom-properties设preserve:false静态替换;变量须定义在:root、值为静态常量,calc()内嵌var()需手动拆解,兜底推荐no-cssvars类而非@supports。

var(--x) 在 IE11 及更早版本中根本不会被解析,整条 CSS 声明会被静默丢弃——不是“颜色没变”,而是 .btn { background: var(--primary); } 在 IE 里等同于 .btn { }。靠后备值 var(--x, #fff) 或 @supports 都救不了,必须用构建时静态替换。
postcss-custom-properties 必须设 preserve: false
默认配置下,插件只生成双声明:background: #007bff; background: var(--primary);。IE 看到第二行就跳过,最终取继承值或初始值(比如透明背景、黑色文字),样式大面积丢失。
-
preserve: false才会真正移除var()调用,只保留降级后的静态值 - 若你同时用
css-vars-ponyfill,它依赖原始var()存在来运行时替换;此时必须配preserve: true,但 IE 下就会双失效——PostCSS 没删掉var(),ponyfill 又因变量未定义或作用域不对而跳过 - Webpack/Vite 项目中,确保插件顺序在
autoprefixer之前,否则可能被后续处理干扰
变量必须定义在 :root 且值为静态常量
PostCSS 插件是编译期工具,看不到 JS 动态设置的变量,也读不到跨文件定义的内容。所有能被降级的变量,必须满足:
- 声明在
:root最稳妥;.card { --pad: 1rem; }这类局部定义默认不处理,除非显式配importFrom指向该文件 - 值只能是纯常量:
--color: red;✅,--size: calc(1rem + 2px);❌,--c: var(--base);❌ - 媒体查询内定义的变量(如
@media (min-width: 768px) { :root { --gap: 16px; } })通常无法被回溯解析,建议提至顶层
@supports 和 no-cssvars 类才是真实兜底手段
@supports (background: var(--x)) 在 IE 中本身不被识别,会直接忽略整条规则。它只能用于现代浏览器的增强逻辑,不能单独作为降级依据。
- 正确做法是前置静态值、后置
var()覆盖:background: #007bff; background: var(--primary);,顺序不能颠倒 - JS 检测应使用
CSS.supports('color', 'var(--theme)'),而非CSS.supports('--theme')(后者在 IE 报TypeError) - 给
加no-cssvars类最可靠:<script>if (!CSS.supports('color', 'var(--_)')) document.documentElement.classList.add('no-cssvars');</script>,再写.no-cssvars .btn { background: #007bff; }
别指望 calc() 里套 var() 能被自动处理
width: calc(100% - var(--gap)) 在 IE 中不是 “var() 不生效”,而是整个 calc() 表达式被 parser 直接跳过。PostCSS 默认不处理这种嵌套,因为无法安全求值。
-
postcss-custom-properties不负责解析calc()内部;postcss-calc也需手动接入且顺序严格(必须在 custom-properties 之后) - 稳妥做法:把
--gap: 12px这种纯数值变量,直接写成width: calc(100% - 12px) - 如果
gap需动态,就得 JS 注入内联样式,或放弃 IE11 支持
真正麻烦的是变量来源混杂:一部分来自 JSON 主题配置,一部分由 JS 动态注入,一部分写在组件级 CSS 中。这些场景 PostCSS 都捕获不到,css-vars-ponyfill 也未必能覆盖全——最终得靠 class 切换 + 静态 fallback 组合拳,而不是寄希望于某一个工具自动搞定。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











