什么是 PostCSS?如何使用插件自动化 CSS 任务
Category(分类): CSS Status: 未知
本文整理自早期 PostCSS 学习资料,保留原文对常用插件、CLI、配置文件和任务运行器的介绍,并修正插件定位、现代 CSS 嵌套、Autoprefixer 输出、Stylelint 配置和安装命令等问题。
什么是 PostCSS?
PostCSS 是一个基于 JavaScript 的 CSS 处理工具。它可以:
- 将 CSS 源码解析为抽象语法树(AST);
- 按顺序运行一个或多个插件;
- 由插件分析、转换或检查 AST;
- 将处理后的 AST 输出为 CSS,并在需要时生成 source map。
PostCSS 本身主要负责解析、插件调度和输出,不会自动提供变量、嵌套、混合或浏览器前缀。具体能力来自插件,例如:
postcss-import:在构建阶段内联 CSS 文件;- Autoprefixer:根据目标浏览器补充必要的厂商前缀;
postcss-preset-env:根据目标浏览器转换部分现代 CSS;postcss-nested:处理嵌套规则;postcss-mixins:提供 Mixin 语法;- Stylelint:检查 CSS 代码,但通常作为独立工具运行;
- Cssnano:压缩生产环境的 CSS。
因此,PostCSS 既不能简单称为预处理器,也不能简单称为后处理器。它是一套 CSS 处理基础设施,既可以在预处理阶段使用,也可以在兼容性转换、代码检查和压缩阶段使用。
可以把 PostCSS 与 Babel 作类比:两者都可以解析源码、运行插件并输出转换后的代码,但 PostCSS 专门处理 CSS 及相关语法。
PostCSS 能否替代 Sass、Less?
PostCSS 可以与 Sass、Less 和 Stylus 一起使用,也可以通过插件实现部分类似功能,但不能默认认为它是这些预处理器的完全替代品。
选择哪种方案取决于项目需求:
- 只需要浏览器兼容性转换,可以使用 PostCSS 和 Autoprefixer;
- 需要现代 CSS 降级,可以使用
postcss-preset-env; - 需要 Sass 风格变量、Mixin 和函数,应评估 Sass 或对应 PostCSS 插件;
- 已经使用 Sass 时,可以先由 Sass 生成 CSS,再交给 PostCSS 继续处理。
PostCSS 与 Vite、Next.js、Tailwind CSS
许多构建工具支持读取 PostCSS 配置,例如 Vite 和 Next.js。是否实际运行哪些插件,取决于项目依赖和配置,不能仅因为使用了这些工具就认为所有 PostCSS 插件都已启用。
Tailwind CSS 是 CSS 框架和工具链,不应直接称为“一个 PostCSS 插件”。某些版本或集成方式会通过 PostCSS 插件运行 Tailwind 的处理流程,但 Tailwind CSS 本身不等同于 PostCSS 插件。
PostCSS 的特点和优势
可组合和可定制
PostCSS 的处理能力由插件组合而成,项目只需要引入真正使用的插件:
源码 CSS → 导入 → 嵌套/变量转换 → 兼容性处理 → 压缩 → 输出 CSS
插件顺序会影响结果。例如:
postcss-import通常应尽量放在前面;- Mixin、变量和嵌套插件通常应在 Autoprefixer 之前运行;
- Cssnano 通常放在处理链末尾;
- Stylelint 通常作为独立检查命令运行,而不是加入转换链。
构建速度
PostCSS 的构建速度取决于插件数量、文件规模、压缩设置、source map、缓存和构建工具。不能笼统地断言它一定比所有预处理器更快。选择 PostCSS 的主要理由应是插件生态、可组合性和与现有构建工具的集成能力。

自定义插件
如果现有插件不能满足需求,可以使用 PostCSS API 编写自定义插件,对 AST 进行检查或转换。PostCSS 生态中的插件数量会随着时间变化,不应引用固定的“356 个插件”作为当前数据。
可以在以下目录查找插件:
常用 PostCSS 插件
1. postcss-import
postcss-import 可以在构建阶段将一个 CSS 文件导入另一个 CSS 文件:
/* src/style.css */
@import './components/comp1.css';
@import './components/comp2.css';
.page {
color: #222;
}
它与 Sass 中的 @import 看起来相似,但处理时机不同。postcss-import 通常在构建时内联文件,浏览器最终接收到的是合并后的 CSS。
这与浏览器原生 CSS @import 不同。原生 @import 会在浏览器运行时继续请求被导入的样式表,可能形成请求链;如果导入关系可以在构建阶段确定,通常可以使用 postcss-import 处理。
需要注意:
@import通常应位于其他 CSS 规则之前;- 导入路径和扩展名要正确;
- 循环导入会导致构建问题;
- 动态决定的样式资源不一定适合在构建阶段内联。
2. Autoprefixer:自动添加厂商前缀
Autoprefixer 根据 Browserslist 查询和兼容性数据,为目标浏览器补充必要的厂商前缀。它不会无条件添加 -webkit-、-moz- 和 -ms-,实际输出取决于目标浏览器和 Autoprefixer 版本。
输入:
label {
user-select: none;
}
::selection {
color: white;
background: blue;
}
::placeholder {
color: gray;
}
在面向现代浏览器的配置下,可能几乎不需要额外前缀;如果目标浏览器包含较旧版本,输出可能包含类似下面的内容:
label {
-webkit-user-select: none;
user-select: none;
}
::selection {
color: white;
background: blue;
}
旧版浏览器目标还可能生成 ::-moz-selection、::-moz-placeholder 或 :-ms-input-placeholder。这些前缀只是特定 Browserslist 配置下的示例,不应视为固定输出。
Autoprefixer 使用 Browserslist 来指定目标浏览器。例如在 package.json 中:
{
"browserslist": [
"defaults"
]
}
也可以在项目根目录创建 .browserslistrc:
defaults
defaults 是一个会随 Browserslist 数据更新而变化的查询集合,不应把某一时期的浏览器版本列表当作永久固定值。项目也可以根据实际需求配置:
{
"browserslist": [
"last 2 versions",
"not dead",
"iOS >= 14"
]
}
3. postcss-preset-env
postcss-preset-env 允许开发者使用部分现代 CSS,并根据目标浏览器进行转换。它可以处理现代 CSS 特性,例如部分嵌套、自定义媒体查询、逻辑属性和自定义选择器。
stage 用于控制启用的特性阶段,常见取值为 0 到 4,也可以设置为 false。具体可用特性和默认值应以当前插件版本文档为准。示例:
// postcss.config.cjs
module.exports = {
plugins: [
require('postcss-preset-env')({
stage: 2
})
]
}
现代浏览器已经支持原生 CSS Nesting,但如果项目需要兼容较旧浏览器,仍然可以让 preset-env 根据 Browserslist 进行转换。不要再笼统地说“现在的 CSS 不支持嵌套”。
输入:
article {
background: purple;
& .title {
font-size: 6rem;
}
& li {
list-style: none;
}
}
在目标浏览器不支持嵌套时,可能转换为:
article {
background: purple;
}
article .title {
font-size: 6rem;
}
article li {
list-style: none;
}
实际输出取决于插件版本、Browserslist 和具体特性配置。postcss-preset-env 通常也会集成 Autoprefixer,但仍应根据当前版本文档确认配置和输出。
4. postcss-nested
如果只想处理较接近 Sass 风格的嵌套,可以使用 postcss-nested:
.card {
color: #222;
& .title {
font-weight: 700;
}
}
postcss-nested 与 postcss-preset-env 的目标并不完全相同:前者更偏向 Sass 风格嵌套,后者更偏向根据目标浏览器转换标准或拟标准 CSS 特性。两者的输出不一定完全相同,不应重复启用相同功能而不进行测试。
5. postcss-mixins
Mixin 可以定义一组可复用的样式。经典 postcss-mixins 插件的语法示例:
@define-mixin reset-list {
margin: 0;
padding: 0;
list-style: none;
}
nav ul {
@mixin reset-list;
}
转换结果:
nav ul {
margin: 0;
padding: 0;
list-style: none;
}
需要注意不同 Mixin 插件包的语法可能不同。上面的 @define-mixin / @mixin 是经典 postcss-mixins 包的写法,不能与其他插件的 CSS Mixins 语法混用。
6. Stylelint:CSS 代码检查
Stylelint 是 CSS、SCSS 等样式代码的检查工具,可以发现无效颜色、未知属性、选择器问题和团队规范问题。它通常独立运行,不应直接把 require('stylelint') 放入普通 PostCSS 转换插件数组。
例如创建 .stylelintrc.json:
{
"rules": {
"color-no-invalid-hex": true
}
}
下面的颜色会触发检查:
.invalid {
color: #12xz;
}
执行检查:
pnpm exec stylelint "src/**/*.css"
也可以在 package.json 中添加脚本:
{
"scripts": {
"lint:css": "stylelint \"src/**/*.css\""
}
}
默认情况下,Stylelint 不会启用所有规则。需要在配置文件中明确开启规则,或继承社区共享配置。

参考:Stylelint
7. Cssnano:CSS 压缩
Cssnano 用于减少生产环境 CSS 的体积,常见操作包括:
- 删除不必要的空白和换行;
- 删除部分冗余声明;
- 压缩颜色值;
- 优化规则和声明;
- 删除可安全删除的注释。
输入:
* {
padding: 0;
margin: 0;
}
body {
font-family: sans-serif, Calibri;
font-size: 16px;
}
nav ul {
margin: 0;
padding: 0;
list-style: none;
}
压缩后可能类似:
*{margin:0;padding:0}body{font-family:sans-serif,Calibri;font-size:16px}nav ul{list-style:none;margin:0;padding:0}
具体结果取决于 Cssnano 版本、preset 和配置。CSS 自定义属性不能在不了解引用关系的情况下任意重命名,不能把“重命名变量”作为普遍行为。
Cssnano 通常应放在处理链的后面:
require('cssnano')({
preset: 'default'
})
参考:Cssnano
8. postcss-normalize
postcss-normalize 可以根据配置引入 normalize.css 或 sanitize.css 的部分内容,帮助处理浏览器默认样式差异:
module.exports = {
plugins: [
require('postcss-normalize')
]
}
它的具体输出会受到 Browserslist 和插件配置影响。使用前应确认项目是否已经通过 CSS Reset、组件库或框架提供了同类功能,避免重复引入。
如何设置 PostCSS
安装依赖
推荐将依赖安装在项目本地,而不是全局安装:
pnpm add -D postcss postcss-cli postcss-import postcss-mixins postcss-preset-env cssnano
pnpm add -D stylelint
如果项目使用 npm,可以使用对应的 npm install -D 命令。全局安装 postcss-cli 或 grunt-cli 容易造成不同项目之间的版本不一致,通常不推荐。
PostCSS 核心包本身不提供所有插件功能;使用哪些能力就需要安装对应插件。
使用 PostCSS CLI
PostCSS CLI 的常用形式是:
postcss <input.css> -o <output.css>
postcss <input.css> --dir <output-directory>
postcss <input.css> -o <output.css> --watch
例如:
pnpm exec postcss src/style.css -o public/style.css
如果不使用配置文件,也可以通过 --use 指定插件:
pnpm exec postcss src/style.css \
--use postcss-import \
--dir public \
--watch
其中:
--use:指定要使用的插件;--dir:指定输出目录;-o或--output:指定输出文件;--watch或-w:监听输入文件变化并重新构建。
直接在命令中写入多个插件会使命令变长,因此项目通常使用 postcss.config.cjs 或 postcss.config.js。
通过 package.json 脚本运行
{
"scripts": {
"postcss:build": "postcss src/style.css -o public/style.css",
"postcss:watch": "postcss src/style.css -o public/style.css --watch"
}
}
运行:
pnpm run postcss:build
pnpm run postcss:watch
如果使用 --dir public,例如:
postcss src/style.css --dir public
输入文件名为 style.css 时,通常会在 public 目录下生成同名文件。如果希望自定义输出文件名,应使用 -o:
postcss src/style.css -o public/main.css
通过配置文件运行 PostCSS
在项目根目录创建 postcss.config.cjs:
module.exports = {
plugins: [
require('postcss-import'),
require('postcss-mixins'),
require('postcss-preset-env')({
stage: 2
}),
require('cssnano')({
preset: 'default'
})
]
}
插件顺序通常应考虑以下原则:
postcss-import尽量放在前面,让后续插件能够处理被导入的内容;- Mixin、变量、嵌套等语法转换应在兼容性处理和压缩之前;
- Autoprefixer 或 preset-env 应在压缩之前;
- Cssnano 通常放在最后;
- Stylelint 使用独立命令,不放入上述转换数组。
如果项目的 package.json 设置了:
{
"type": "module"
}
可以使用 postcss.config.cjs 保持 CommonJS 配置;如果使用 postcss.config.js,则应根据构建工具的模块格式要求使用 export default。
使用任务运行器或模块打包器
PostCSS 也可以与 Gulp、Grunt、Rollup、Webpack 等工具集成。现代项目通常由 Vite、Webpack 或其他构建工具加载 PostCSS 配置,只有维护旧项目时才更常见地直接使用 Grunt。
使用 Grunt
安装依赖:
pnpm add -D grunt grunt-cli @lodder/grunt-postcss
pnpm add -D postcss-import postcss-mixins postcss-preset-env cssnano
在项目根目录创建 Gruntfile.js:
module.exports = function (grunt) {
grunt.initConfig({
postcss: {
options: {
processors: [
require('postcss-import')(),
require('postcss-mixins'),
require('postcss-preset-env')({
stage: 2
}),
require('cssnano')({
preset: 'default'
})
]
},
dist: {
src: 'src/style.css',
dest: 'public/style.css'
}
}
})
grunt.loadNpmTasks('@lodder/grunt-postcss')
}
这里需要注意:
- 正确的方法名是
grunt.initConfig,不是initCnfig; processors中应放 PostCSS 转换插件;- Stylelint 应单独执行,不应作为这里的普通处理器;
cssnano通常放在处理链最后;- 不同版本的 Grunt 插件对处理器配置可能略有差异,应以实际插件文档为准。
运行任务:
pnpm exec grunt postcss
什么时候使用 PostCSS?
适合使用 PostCSS 的场景包括:
- 需要根据 Browserslist 自动添加浏览器前缀;
- 需要将部分现代 CSS 转换为旧浏览器可以理解的语法;
- 需要构建阶段内联 CSS 文件;
- 需要把 CSS 检查、转换和压缩接入构建流程;
- 需要编写自定义 CSS 转换插件;
- 已经使用 Vite、Webpack、Rollup 等支持 PostCSS 的构建工具。
不应为了“使用 PostCSS”而堆叠大量插件。插件越多,构建时间、调试难度和输出差异也可能增加。应根据目标浏览器、项目语法和部署需求选择最小可用配置。
总结
- PostCSS 核心负责 CSS AST 的解析、插件调度和输出;
- PostCSS 的具体功能来自插件,不是一个自带全部特性的预处理器;
postcss-import通常在构建阶段内联 CSS,和浏览器原生@import不同;- Autoprefixer 的输出取决于 Browserslist 和目标浏览器,不会固定添加所有厂商前缀;
- 现代浏览器已经支持 CSS Nesting,但旧浏览器兼容仍可能需要 preset-env 或嵌套插件;
postcss-preset-env、postcss-nested和postcss-mixins的语法和目标并不完全相同;- Stylelint 通常作为独立的 CSS 检查工具运行,不应直接放进普通 PostCSS 插件数组;
- Cssnano 一般放在处理链最后,并且压缩结果取决于版本和 preset;
- 推荐使用项目本地依赖、配置文件和 package scripts,不建议依赖全局 CLI;
- PostCSS 是否适合项目,应根据浏览器目标、代码规模、插件需求和构建工具综合判断。
参考资料
- PostCSS 官方文档
- PostCSS 插件目录
- postcss-import
- Autoprefixer
- Browserslist
- postcss-preset-env
- postcss-nested
- postcss-mixins
- Stylelint
- Cssnano
- PostCSS CLI
原文资料:2022 首次更文挑战