PostCSS-preset-env的stage参数是特性准入门槛而非功能开关,设stage:3表示仅考虑成熟度≥Stage 3(W3C候选推荐)的特性,再结合browserslist和features配置二次筛选;stage值0–4对应不同标准化阶段,需与browserslist协同生效,单独调低stage并不提升兼容性,最终是否转译取决于目标浏览器实际支持情况。

stage 不是功能开关,而是特性准入门槛
设 stage: 3 并不等于“只开 Stage 3 特性”,而是告诉 postcss-preset-env:只考虑成熟度 ≥ Stage 3 的特性(即已进入 W3C 候选推荐的特性)。它会基于 browserslist 和 features 配置再做二次筛选。比如 color-mix() 当前仍是 Stage 3,若你设了 stage: 4,它反而被排除——因为 Stage 4 是已发布标准,而该函数还没到那一步。
stage 值选 0–4,实际效果差异很大
不同 stage 对应的特性范围不是线性扩展,而是按 CSS 标准演进阶段划分:
-
stage: 0:连实验性语法(如@property)都尝试启用,但多数无 polyfill,仅语法解析,容易报错或无效 -
stage: 2:覆盖大部分可用特性,如嵌套规则、自定义媒体查询、逻辑属性等,适合激进尝鲜 -
stage: 3:最常用平衡点,支持nesting-rules、custom-properties、inset、font-variation-settings等,且 polyfill 较稳定 -
stage: 4:仅包含已发布标准,实际启用特性极少(如部分accent-color行为),基本等价于关掉大部分未来语法转换
单独开启某个 stage 未覆盖的特性,用 features 覆盖
即使 stage: 3,你仍可通过 features 手动启用一个 Stage 2 特性,比如 logical-properties-and-values:
require('postcss-preset-env')({
stage: 3,
features: {
'logical-properties-and-values': true
}
})
这种写法有效,但要注意:
立即学习“前端免费学习笔记(深入)”;
- 该特性必须在
cssdb中标记为「可 polyfill」,否则只是语法通过,无实际降级输出 - 某些特性(如
container-query)虽在 Stage 3,但依赖运行时 JS 检测,postcss-preset-env不处理,需配合@csstools/postcss-plugins等补充方案 - 开启
'nesting-rules': true后,&:hover不会自动提升父选择器权重,编译后仍是原始语义,别指望它能解决 specificity 问题
stage 和 browserslist 必须配合使用,缺一不可
stage 决定“哪些特性有资格参与编译”,browserslist 决定“哪些特性需要被降级”。两者共同作用才生效:
- 没配
.browserslistrc或package.json里的browserslist字段,postcss-preset-env会退回到默认目标(通常是last 2 versions),但 stage 判断可能失准 - 写了
"Chrome >= 87"却设stage: 3,像inset这类特性就不会编译——因为 Chrome 87 已原生支持,插件认为无需降级 - 想强制让
inset: 0编译成top:0;right:0;bottom:0;left:0,得把 browserslist 放宽到"Chrome >= 79"或更低
真正容易被忽略的是:stage 数值调低 ≠ 兼容性变好,它只扩大候选池;最终是否生成降级代码,取决于你的浏览器目标是否真的不支持那个特性。


















