postcss-preset-env 不自动降级,必须显式配置 stage(推荐 stage: 3)和 targets(如 {chrome: '45', ie: '11'}),并关闭内置 autoprefixer;css 变量需用 postcss-custom-properties 且 preserve: false 才能转译,ie11 中 @supports 无效,须用 no-cssvars 类兜底;gap、aspect-ratio、:has() 等无法自动降级,需手动替代实现。

postcss-preset-env 的 stage 和 targets 必须显式配置
它不是装上就自动降级的“智能开关”。不写 stage 和 targets,大部分新语法(比如 @container、& 嵌套、aspect-ratio)会原样输出,老浏览器直接忽略或报错。
stage: 3 是最实用起点——覆盖 nesting、custom-properties、logical-properties 等已稳定提案;stage: 4(如 color-mix())通常不转换,得靠 polyfill。
targets 要具体到版本号,不能只靠 .browserslistrc:
- ✅ { chrome: '45', ie: '11', safari: '10' }
- ❌ 空着、或只写 ['last 2 versions'](IE11 不在其中,@container 就不会被处理)
还要关掉 preset-env 内置的 autoprefixer:autoprefixer: false,否则和你单独配的 autoprefixer 插件冲突。
CSS 变量必须用 postcss-custom-properties + preserve: false
var(--c) 在 IE11 里不是“颜色不对”,而是整条声明被静默丢弃。靠 background: var(--c, #000) 或 @supports 都无效——IE 连 @supports 语法都不认识。
真正起作用的是:postcss-custom-properties 插件设 preserve: false,它才会把 background: var(--primary) 替换成 background: #007bff 并删掉原始行。
但这个插件有硬限制:
- 变量必须定义在 :root,且值为静态常量(--gap: 16px ✅,--gap: calc(1rem) ❌)
- 不处理 JS 动态设置的变量(el.style.setProperty('--c', 'red'))
- 插件顺序必须在 autoprefixer 之前,否则前缀可能加错位置
@supports 不是兼容方案,no-cssvars 类才是
@supports (background: var(--x)) { ... } 在 IE 中整条规则被跳过,根本不会生效。它只适合现代浏览器做渐进增强,不能当降级兜底。
真实可用的 fallback 方式是:
- JS 检测:CSS.supports('color', 'var(--_)')(注意不是 CSS.supports('--theme'),后者在 IE 报错)
- 给 加类:document.documentElement.classList.add('no-cssvars')
- 写两套样式:.btn { background: var(--primary); } .no-cssvars .btn { background: #007bff; }
别把希望全押在构建时降级上。动态主题、JS 注入变量、媒体查询内定义的变量……这些场景下,no-cssvars 类仍是最后一道防线。
gap / aspect-ratio / :has() 这些压根没法自动降级
PostCSS 不改语义,也不生成替代布局。像 gap、aspect-ratio、:has() 这类特性,postcss-preset-env 和 autoprefixer 都不会碰——它们连前缀都没有,更别说模拟实现了。
你必须手动处理:
- gap: 16px → 改用 margin 或 padding 模拟
- aspect-ratio: 16/9 → 改用 padding-top: 56.25% + position: relative/absolute 结构
- :has(.active) → 换成 JS 添加 class 或服务端渲染标记
构建工具再强,也替代不了你对旧浏览器渲染逻辑的理解。漏掉这类手动适配,光靠 PostCSS 链,上线后 IE11 里大概率白屏或布局崩塌。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











