CSS – PostCSS
前言
我第一次接触 PostCSS 是在学 Tailwind CSS 的时候. 它类似 JavaScript 的 Babel.
我没有用过 Babel, 因为 TypeScript 用的早. PostCSS 也是这样, Sass 用的早.
PostCSS 具备一部分 (甚至大部分 Sass 的能力), 而且还多了其它能力. 所以会看到一些人纷纷从 Sass 转到了 PostCSS.
但据我个人的经验. 我更推荐 2 个一起用. 尤其是在 Production 的时候. 可以参考我从前写的 Webpack 学习笔记.
写代码一样用 Sass, 然后 transpile 成 CSS 后再用 PostCSS 加工 (e.g. 向后兼容).
这篇只是一个简单的 Get Started 体验一下单独使用 PostCSS.
参考
YouTube – Learn how to power-up your CSS with PostCSS
YouTube – Learn PostCSS In 15 Minutes
Simple Start
创建项目
PostCSS 不像 Sass 那样可以安装 VS Code 插件, 它需要使用 Node.js + PostCSS CLI 然后跑 command 来启动.
先创建 folder 初始化 Node.js 项目
mkdir postcss-get-started
cd postcss-get-started
yarn init -2
我习惯用 yarn package manager, 换成 npm init 也是可以的.
安装 PostCSS CLI
yarn add postcss postcss-cli --dev
安装 postcss 和 postcss-cli. 我们先学 cli 版本, 下面我还会教 gulp 的版本.
Setup Files
package.json 启动 script
{
"scripts": {
"start": "postcss style.css -o dist/style.css --watch"
}
}
style.css
body {
background-color: pink;
}
command
yarn start
效果

至此 PostCSS 就算运行起来了. 但是它还没有任何作用. 这是因为 PostCSS 是基于插件的. 任何对 CSS 的处理都需要用插件来完成.
常用插件
postcss-preset-env
这个插件是最重要的, 也是我唯一使用的. 它的作用就是向后兼容. 比如
@media (width >= 1024px) {}
// will transpile to
@media (min-width : 1024px) {}
Sass 做不到这种 transpile 的效果. 这时就可以靠 PostCSS 来完成了.
安装
yarn add postcss-preset-env --dev
setup postcss.config.js, 引入 plugin
const postcssPresetEnv = require("postcss-preset-env");
module.exports = {
plugins: [
postcssPresetEnv({ stage: 1 }),
],
};
setup browserlist (在 package.json)
{
"browserslist": [
"since 2021 and not ios < 15"
]
}
效果

解释:
1. postcssPresetEnv({ stage: 1 }) 里的 stage 代表 CSS 支持的状态. 0 是 experimental, 4 是 stable. 它的 default 是 2, 我通常放 1.
2. 必须要提供 browserslist, 这样它才知道需不需要 Polyfill. 关于 browserlist 可以参考:
它就是一个 config, 声明项目支持什么 browser version. 它可以用一些很牛的表达式
比如 since 2021 and not < ios 15, 表示要支持 2021 年以后版本的 browser 同时 IOS safari 必须超过 v15. 这个表达式的数据是依据 Can i use 网站的
通过在线工具, 我们还可以查看表达式最终匹配支持的 browser 哦

postcss-import
这个插件可以让 PostCSS transplie 的时候把 import 的 CSS bundle 在一起.
安装
yarn add postcss-import --dev
setup postcss.config.js, 引入 plugin
const postcssPresetEnv = require("postcss-preset-env");
const postcssImport = require("postcss-import");
module.exports = {
plugins: [
postcssPresetEnv({ stage: 1 }),
postcssImport(),
],
};
reset.css
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
style.css (import reset.css)
@import "./reset.css";
body {
background-color: pink;
}
效果

最终 reset.css 被 bundle 到了 dist/style.css 里头
postcss-nested
和 Sass 的 nested 是一样的. 所以说 PostCSS 具有替代 Sass 的能力.
安装 > plugin > 效果 和上面的雷同, 我就不讲解了.
注: 在 VS Code, .css 写 nested 虽然不会语法报错, 但它也不太智能. 不会比写 Sass 的体验好.
postcss-simple-vars
和 Sass 的 Variable 是一样的.
postcss-mixins
和 Sass 的 mixins 功能是一样的. 但是语法不同
postcss.config.js (注意: mixin 必须在 nested 和 variable 之前哦)
const postcssPresetEnv = require("postcss-preset-env");
const postcssImport = require("postcss-import");
const postcssMixins = require("postcss-mixins");
const postcssNested = require("postcss-nested");
const postcssSimpleVars = require("postcss-simple-vars");
module.exports = {
plugins: [
postcssPresetEnv({ stage: 1 }),
postcssImport(),
postcssMixins(), // 必须 before nested 和 variable
postcssNested(),
postcssSimpleVars(),
],
};
style.css
@import "./reset.css"; /* variable */
$size: 100px; /* mixin 声明方法 */
@define-mixin method-name $color, $size: 100px {
background-color: $color;
width: $size;
@mixin-content;
} body {
background-color: pink; /* nested */
.container {
width: $size;
} /* mixin 调用方法 */
@mixin method-name red, 50px {
height: 100%;
}
}
效果

postcss-font-magician
我在 Webpack 学习笔记 介绍过这个插件, 虽然已经停更了, 但 for 小网站还是适用的.
安装
yarn add postcss-font-magician --dev
config
postcss([
postcssPresetEnv({ stage: 1 }),
postcssFontMagician({
custom: {
Montserrat: {
variants: {
normal: {
300: {
url: {
woff2: "/src/fonts/montserrat-v25-latin-300.woff2",
woff: "/src/fonts/montserrat-v25-latin-300.woff",
},
},
400: {
url: {
woff2: "/src/fonts/montserrat-v25-latin-regular.woff2",
woff: "/src/fonts/montserrat-v25-latin-regular.woff",
},
},
500: {
url: {
woff2: "/src/fonts/montserrat-v25-latin-500.woff2",
woff: "/src/fonts/montserrat-v25-latin-500.woff",
},
},
700: {
url: {
woff2: "/src/fonts/montserrat-v25-latin-700.woff2",
woff: "/src/fonts/montserrat-v25-latin-700.woff",
},
},
},
},
},
},
display: "swap",
}),
])
效果

只要 CSS 中有时用到对应的字体
transpile 出来的 CSS 自动包含 @font-face 代码

cssnano
nano 的用途是 minifier css. 很久以前我写的 Webpack 学习笔记 – Optimization 里头用的 css-minimizer-webpack-plugin 底层就是用了 cssnano 做 minify.
用法很简单
postcss([
require("postcss-preset-env")({ stage: 1 }),
require("postcss-import")(),
require("postcss-mixins")(),
require("postcss-nested")(),
require("postcss-simple-vars")(),
require("cssnano")({
preset: ["default", { cssDeclarationSorter: false }],
}),
])
效果

左边是没有使用 nano 的结果, 右边是用了 nano 的结果.
它做了几件事, 比如, 去掉了空格空行, 去掉了 column-gap: initial. 还有它对属性做了排序. column-gap 被移到 gap 前面了.
这个改动通常是不好的. 因为 CSS 是讲究属性顺序的, 后面的 override 前面的. 所以这种排序很可能会破坏表达.
通过 cssDeclarationSorter: false 可以关掉它. 这样它就不会乱排了. 参考: Stack Overflow – cssnano is reordering overridden properties
小总结
PostCSS 的插件很强, 理论上可以替代任何 Sass 的功能的. 但前提是要有人去贡献这些插件.
当然这是不可能的, 哪来这么多贡献呢 ... /.\ 所以我个人还是觉得 Sass + PostCSS 一起用才实际.
Sass + PostCSS with Gulp
在搭建测试环境时, 我们不喜欢用 bundle tool, Webpack 也好, Vite 也好都算比较上层的东西.
我们更喜欢用底层的 Gulp, 这样可以憋开不必要的东西进来搅局. 这里教大家用 Gulp 搭建简单的 Sass + PostCSS 测试环境.
Gulp 基础参考:
对比webpack,你更应该先掌握gulp【10分钟教你彻底掌握gulp】
Stack Overflow – Pass Parameter to Gulp Task
YouTube – Learn PostCSS: How To Setup PostCSS With Gulp
Gulp PostCSS
安装 Gulp 和 gulp-postcss
npm install --global gulp-cli
yarn add gulp --dev
yarn add gulp-postcss --dev
yarn add gulp-sourcemaps --dev
gulpfile.js
// import 需要用到的 gulp 方法
const { src, dest, watch: gulpWatch } = require("gulp"); // postcss 需要的 gulp plugin
const postcss = require("gulp-postcss");
const sourcemaps = require("gulp-sourcemaps"); const cssPath = "style.css";
// 定义 task
function postcssTask() {
return src(cssPath) // read files
.pipe(sourcemaps.init())
.pipe(
// 用 postcss 处理 file stream
postcss([
require("postcss-preset-env")({ stage: 1 }),
require("postcss-import")(),
require("postcss-mixins")(),
require("postcss-nested")(),
require("postcss-simple-vars")(),
])
)
.pipe(sourcemaps.write("."))
.pipe(dest("dist/")); // write files
} // 定义 yarn run gulp 默认执行的 tasks
exports.default = function () {
// 通过 yargs 获取 yarn run gulp --watch 的 --watch parameters
var { watch } = require("yargs").argv;
return watch ? gulpWatch(cssPath, postcssTask) : postcssTask();
}; // 如果不想使用 parameter 控制 watch, 也可以定义 2 个 tasks, 调用变成 yarn run gulp watch 和 yarn run gulp build
// exports.watch = function () {
// gulpWatch(cssPath, postcssTask);
// }
// exports.build = postcssTask;
plugin 可以在 gulpfile.js 里, 也可以定义到 postcss.config.js. 但注意, postcss.config.js 这个 file 是一定要有的, 哪怕只是 module.exports = {}; 不然会报错哦
postcss.config.js
module.exports = {}
Run Command
"scripts": {
"start": "gulp build" // or gulp watch or gulp --watch
},
Gulp Sass
Gulp PostCSS + Sass
gulpfile.js
const { src, dest, watch } = require("gulp");
const sass = require("gulp-sass")(require("sass"));
const sourcemaps = require("gulp-sourcemaps");
const postcss = require("gulp-postcss");
const postcssPresetEnv = require("postcss-preset-env");
function sassTask() {
return src("./src/**/*.scss")
.pipe(sourcemaps.init())
.pipe(sass().on("error", sass.logError))
.pipe(postcss([postcssPresetEnv({ stage: 1 })])) // 这里多了一个 postcss pipe
.pipe(sourcemaps.write("."))
.pipe(dest("src/"));
}
exports.build = sassTask;
exports.watch = function () {
watch("./src/**/*.scss", sassTask);
};
run command
yarn run gulp build // or yarn run gulp watch
效果

Gulp Multi Tasks
这个和 PostCSS 没关系, 只是 Gulp 的功能之一. 随便介绍一下 (内容多一点才考虑开一篇 Gulp 的)
Stack Overflow – Gulpjs combine two tasks into a single task
这里给一个 SVG sprite 的例子
const { src, dest, parallel } = require("gulp");
const svgSprite = require("gulp-svg-sprite");
function spriteSvgIconTask() {
return src("src/icons/*.svg")
.pipe(
svgSprite({
mode: {
symbol: true,
},
})
)
.pipe(dest("src/icons/svg-icon-sprite"));
}
function spriteSvgIconTask2() {
return src("src/stooges-icons/*.svg")
.pipe(
svgSprite({
mode: {
symbol: true,
},
})
)
.pipe(dest("src/stooges-icons/svg-icon-sprite"));
}
exports.spriteSvgIcon = parallel(spriteSvgIconTask, spriteSvgIconTask2);
parallel 是平行执行, series 是顺序.
当 Gulp 遇上 .cjs
当我们把 module 换成 ES Module 后, 旧版本就得改成 .cjs
这时会发现 gulp command 失效

因为它默认查找的 file 是 .js 而不是 .cjs. 参考: Github Issue – Add support for gulpfile.cjs
解决方法是加 options
gulp spriteSvgIcon -f gulpfile.cjs
CSS – PostCSS的更多相关文章
- [译]PostCSS介绍
PostCSS介绍 原文链接:http://www.smashingmagazine.com/2015/12/introduction-to-postcss/ 转自:http://www.zcfy.c ...
- boi剖析 - 基于webpack的css sprites实现方案
本文是58到家前端工程化集成解决方案boi的博文系列之一.boi是基于webpack打造的一站式前端工程化解决方案,现已开源Github. 作为前端构建工具不可或缺的一个环节,自动生成css spri ...
- PostCss 从0开始
PostCss 摘自 http://ju.outofmemory.cn/entry/215105 http://www.w3cplus.com/PostCSS/postcss-deep-dive-pr ...
- webpack(四)处理 css\less\sass 样式
(一) 处理普通的.css 文件,需要安装 css-loader,style-loader .less 文件,需要安装 less-loader .sass 文件,需安装 less-loader np ...
- [翻译]纠正PostCSS的4大认识误区
市面上已经有很多的前端工具,再来引入新的前端工具,价值大不大?这主要取决于,它是否给开发人员提供了新的功能,是否值得花时间和精力去学习和使用? PostCSS出现时有一个很有趣的现象.像sass和le ...
- webpack之postcss集成
项目 为了 兼容各个浏览器,需要加各种 c3前缀,如果手动的加肯定 相对比较麻烦,但是现在有webpack,gulp之类的 工具可以自动给我们加上,可以说效率上加速不少.如果 配置中 做个happyp ...
- webpack css文件编译、自动添加前缀、剥离
1.css文件编译 webpack默认只能编译js文件,引入css需要loader支持 // css文件写入js中 npm i style-loader -D // css文件loader npm i ...
- 处理CSS前缀问题的神器——AutoPrefixer
众所周知为兼容所有浏览器,有的CSS属性需要对不同的浏览器加上前缀,然而有时添加一条属性,需要添加3~4条类似的属性只是为了满足浏览器的兼容,这不仅会增加许多的工作量. What is AutoPre ...
- postcss 运用及原理
postcss 入坑指南 目标: 掌握 postcss 的使用 自定义 postcss 插件 掌握 stylelint 的使用 自定义 stylelint rule 扩展 css parser 解释器 ...
- webpack+react+antd 单页面应用实例
React框架已经火了好长一段时间了,再不学就out了! 对React还没有了解的同学可以看看我之前的一篇文章,可以快速简单的认识一下React.React入门最好的实例-TodoList 自己从开始 ...
随机推荐
- 学习笔记--Java中this关键字
Java中this关键字 关于Java语言中的this关键字 this 是一个关键字,翻译为:这个 this 是一个引用,一个变量,this变量中保存的内存地址指向自身 每一个对象都有自己的this, ...
- 【JavaScript高级03】执行上下文和执行上下文栈
1,函数提升和变量提升 编写以下代码: var a = 3 function fn () { console.log(a) var a = 4 } fn() 上面的JavaScript代码执行结果为一 ...
- 关于UE5打包DLC
首先打开Project Lanucher,参考下图:,其次编辑配置两个edit Profile,参考下图: 第一个用来打包项目,第二个生成DLC,dlc填写的名字和插件一样,Main的配置如下: DL ...
- web3产品介绍:mask将Web3的隐私和优势引入像Facebook和Twitter这样的社交媒体平台
介绍: Mask Network是一个开源的浏览器扩展,将Web3的隐私和优势引入像Facebook和Twitter这样的社交媒体平台.它是一个功能强大的工具,允许用户在社交媒体上享受区块链的隐私保护 ...
- 对比python学julia(第四章:人工智能)--(第三节)目标检测
1.1. 项目简介 目标检测(Object Detection)的任务是在图像中找出检测对象的位置和犬小,是计算机视觉领域的核心问题之一,在自动驾驶.机器人和无人机等许多领域极具研究价值. 随着深度 ...
- 【Kafka】02 原生集群部署
基于大数据教程的环境: 192.168.101.11 centos7-01 192.168.101.12 centos7-02 192.168.101.13 centos7-03 搭建Kafka环境需 ...
- 【Spring Data JPA】08 多表关系 Part1 一对多关系操作
表关系概述: 1.一 对应 一 一对夫妻,一个男人只能有一个老婆,一个女人只能有一个老公,即这种对应关系 2.一 对应 多 [多对一] 一个年级具有多个班级,一个班级具有对应的所属年级,即这种上下层级 ...
- 【Vue】10 Vue-Cli 项目创建
简单的Demo案例并不需要Vue-Cli,因为一个页面之内可以总揽 但是真实的项目开发,考虑代码结构,目录结构,部署,热部署,单元测试... 代码量呈几何倍数增长,而且缺少轮子就写起来很痛苦 所以必须 ...
- 【转载】英特尔CEO:如果美出口管制太严,中国就必须生产自己的芯片
原文地址: https://mbd.baidu.com/newspage/data/landingsuper?context={"nid"%3A"news_9816136 ...
- Ubuntu 18.04.4 安装docker18.09 (使用阿里云的源)
由于AI_Station 是使用容器构建环境的,而且只提供镜像上传下载功能,不为容易提供网络功能,因此需要在平台上把镜像拉取到本地,并安装一些必备软件然后再打包成镜像上传回去,因此需要在本地构建doc ...