必须设preserve: true——否则旧浏览器因整条声明被静默丢弃而白屏;该配置使PostCSS输出静态值+var()双声明,新旧浏览器各取所需,且需配合:root纯静态变量定义、postcss-preset-env显式启用custom-properties及插件前置运行。
旧浏览器(尤其是 IE11)根本不会解析 var(--x),整条 CSS 声明被静默丢弃——不是 fallback 失效,而是压根没读那行。PostCSS 能解决,但必须手动配对、踩准限制,否则构建后还是满屏 var()。
这是最容易漏掉的关键配置。默认不写或设 preserve: false,输出只剩静态值(如 color: #007bff),新浏览器就失去变量动态能力;设 preserve: true 才会同时输出两行:
color: #007bff;color: var(--primary);
旧浏览器跳过第二行,取第一行;新浏览器优先用第二行,支持 JS 修改、主题切换等。
preserve → 等同于 true?错,实际等同于 false,旧浏览器照样白屏postcss-preset-env?它默认不开 CSS 变量特性,必须显式加 features: { 'custom-properties': true }
postcss-custom-properties 必须在 autoprefixer 之前运行,否则可能被截断PostCSS 插件是构建时静态分析工具,它只认编译期能确定的值。以下写法全会被跳过:
--size: calc(1rem + 2px) → 含 calc(),无法静态求值--c: var(--base) → 引用其他变量,链式依赖不可解.card { --pad: 1rem; } → 局部作用域,默认不处理,除非配 importFrom 显式引入@media (min-width: 768px) { :root { --gap: 16px; } } → 媒体查询内定义,插件通常无法回溯解析稳妥做法:所有变量集中写在 :root,值只用纯字符串或数字,例如 --primary: #007bff;、--gap: 12px;。
width: calc(100% - var(--gap)) 这种写法,在 IE11 不是“var() 不生效”,而是整个 calc() 表达式被 parser 直接跳过——连 fallback 都进不去。
postcss-custom-properties 默认不处理嵌套 var(),哪怕配了 postcss-calc,也得确保执行顺序:先替换变量,再跑 calc--gap: 12px 这类纯数值变量,直接写成 width: calc(100% - 12px)
el.style.width = `calc(100% - ${gap}px)`),或放弃 IE11 支持@supports (background: var(--x)) 在 IE 中会报 TypeError,因为它根本不认识 @supports 语法。运行时检测 CSS.supports('--x') 同样报错。
<html> 加 no-cssvars 类,然后写两套规则:.btn { background: var(--primary); }
.no-cssvars .btn { background: #007bff; }
@supports 块——它不处理语法兼容性,只做静态替换var(--,如果还有未替换的,说明变量定义位置不对、值含动态内容,或插件根本没生效真正麻烦的不是配置本身,而是变量定义和使用之间那些隐式依赖:跨文件引用、JS 动态设置、媒体查询内声明……这些 PostCSS 都看不到,得靠人工梳理清楚才能降级成功。