前言

我第一次接触 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 项目

  1. mkdir postcss-get-started
  2. cd postcss-get-started
  3. yarn init -2

我习惯用 yarn package manager, 换成 npm init 也是可以的.

安装 PostCSS CLI

  1. yarn add postcss postcss-cli --dev

安装 postcss 和 postcss-cli. 我们先学 cli 版本, 下面我还会教 gulp 的版本.

Setup Files

package.json 启动 script

  1. {
  2. "scripts": {
  3. "start": "postcss style.css -o dist/style.css --watch"
  4. }
  5. }

style.css

  1. body {
  2. background-color: pink;
  3. }

command

  1. yarn start

效果

至此 PostCSS 就算运行起来了. 但是它还没有任何作用. 这是因为 PostCSS 是基于插件的. 任何对 CSS 的处理都需要用插件来完成.

常用插件

postcss-preset-env

这个插件是最重要的, 也是我唯一使用的. 它的作用就是向后兼容. 比如

  1. @media (width >= 1024px) {}
  2.  
  3. // will transpile to
  4. @media (min-width : 1024px) {}

Sass 做不到这种 transpile 的效果. 这时就可以靠 PostCSS 来完成了.

安装

  1. yarn add postcss-preset-env --dev

setup postcss.config.js, 引入 plugin

  1. const postcssPresetEnv = require("postcss-preset-env");
  2.  
  3. module.exports = {
  4. plugins: [
  5. postcssPresetEnv({ stage: 1 }),
  6. ],
  7. };

setup browserlist (在 package.json)

  1. {
  2. "browserslist": [
  3. "since 2021 and not ios < 15"
  4. ]
  5. }

效果

解释:

1. postcssPresetEnv({ stage: 1 }) 里的 stage 代表 CSS 支持的状态. 0 是 experimental, 4 是 stable. 它的 default 是 2, 我通常放 1.

2. 必须要提供 browserslist, 这样它才知道需不需要 Polyfill. 关于 browserlist 可以参考:

官方网站

Online Testing Tools

browserslist 是什么?看这篇就够了

browserslist详解

它就是一个 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 在一起.

安装

  1. yarn add postcss-import --dev

setup postcss.config.js, 引入 plugin

  1. const postcssPresetEnv = require("postcss-preset-env");
  2. const postcssImport = require("postcss-import");
  3.  
  4. module.exports = {
  5. plugins: [
  6. postcssPresetEnv({ stage: 1 }),
  7. postcssImport(),
  8. ],
  9. };

reset.css

  1. * {
  2. margin: 0;
  3. padding: 0;
  4. box-sizing: border-box;
  5. }

style.css (import reset.css)

  1. @import "./reset.css";
  2.  
  3. body {
  4. background-color: pink;
  5. }

效果

最终 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 之前哦)

  1. const postcssPresetEnv = require("postcss-preset-env");
  2. const postcssImport = require("postcss-import");
  3. const postcssMixins = require("postcss-mixins");
  4. const postcssNested = require("postcss-nested");
  5. const postcssSimpleVars = require("postcss-simple-vars");
  6.  
  7. module.exports = {
  8. plugins: [
  9. postcssPresetEnv({ stage: 1 }),
  10. postcssImport(),
  11. postcssMixins(), // 必须 before nested 和 variable
  12. postcssNested(),
  13. postcssSimpleVars(),
  14. ],
  15. };

style.css

  1. @import "./reset.css";
  2.  
  3. /* variable */
  4. $size: 100px;
  5.  
  6. /* mixin 声明方法 */
  7. @define-mixin method-name $color, $size: 100px {
  8. background-color: $color;
  9. width: $size;
  10. @mixin-content;
  11. }
  12.  
  13. body {
  14. background-color: pink;
  15.  
  16. /* nested */
  17. .container {
  18. width: $size;
  19. }
  20.  
  21. /* mixin 调用方法 */
  22. @mixin method-name red, 50px {
  23. height: 100%;
  24. }
  25. }

效果

postcss-font-magician

我在 Webpack 学习笔记 介绍过这个插件, 虽然已经停更了, 但 for 小网站还是适用的.

安装

  1. yarn add postcss-font-magician --dev

config

  1. postcss([
  2. postcssPresetEnv({ stage: 1 }),
  3. postcssFontMagician({
  4. custom: {
  5. Montserrat: {
  6. variants: {
  7. normal: {
  8. 300: {
  9. url: {
  10. woff2: "/src/fonts/montserrat-v25-latin-300.woff2",
  11. woff: "/src/fonts/montserrat-v25-latin-300.woff",
  12. },
  13. },
  14. 400: {
  15. url: {
  16. woff2: "/src/fonts/montserrat-v25-latin-regular.woff2",
  17. woff: "/src/fonts/montserrat-v25-latin-regular.woff",
  18. },
  19. },
  20. 500: {
  21. url: {
  22. woff2: "/src/fonts/montserrat-v25-latin-500.woff2",
  23. woff: "/src/fonts/montserrat-v25-latin-500.woff",
  24. },
  25. },
  26. 700: {
  27. url: {
  28. woff2: "/src/fonts/montserrat-v25-latin-700.woff2",
  29. woff: "/src/fonts/montserrat-v25-latin-700.woff",
  30. },
  31. },
  32. },
  33. },
  34. },
  35. },
  36. display: "swap",
  37. }),
  38. ])

效果

只要 CSS 中有时用到对应的字体

transpile 出来的 CSS 自动包含 @font-face 代码

cssnano

nano 的用途是 minifier css. 很久以前我写的 Webpack 学习笔记 – Optimization 里头用的 css-minimizer-webpack-plugin 底层就是用了 cssnano 做 minify.

用法很简单

  1. postcss([
  2. require("postcss-preset-env")({ stage: 1 }),
  3. require("postcss-import")(),
  4. require("postcss-mixins")(),
  5. require("postcss-nested")(),
  6. require("postcss-simple-vars")(),
  7. require("cssnano")({
  8. preset: ["default", { cssDeclarationSorter: false }],
  9. }),
  10. ])

效果

左边是没有使用 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

Gulp 官网

YouTube – Learn PostCSS: How To Setup PostCSS With Gulp

Gulp PostCSS

安装 Gulp 和 gulp-postcss

  1. npm install --global gulp-cli
  2. yarn add gulp --dev
  3. yarn add gulp-postcss --dev
  4. yarn add gulp-sourcemaps --dev

gulpfile.js

  1. // import 需要用到的 gulp 方法
  2. const { src, dest, watch: gulpWatch } = require("gulp");
  3.  
  4. // postcss 需要的 gulp plugin
  5. const postcss = require("gulp-postcss");
  6. const sourcemaps = require("gulp-sourcemaps");
  7.  
  8. const cssPath = "style.css";
  9. // 定义 task
  10. function postcssTask() {
  11. return src(cssPath) // read files
  12. .pipe(sourcemaps.init())
  13. .pipe(
  14. // 用 postcss 处理 file stream
  15. postcss([
  16. require("postcss-preset-env")({ stage: 1 }),
  17. require("postcss-import")(),
  18. require("postcss-mixins")(),
  19. require("postcss-nested")(),
  20. require("postcss-simple-vars")(),
  21. ])
  22. )
  23. .pipe(sourcemaps.write("."))
  24. .pipe(dest("dist/")); // write files
  25. }
  26.  
  27. // 定义 yarn run gulp 默认执行的 tasks
  28. exports.default = function () {
  29. // 通过 yargs 获取 yarn run gulp --watch 的 --watch parameters
  30. var { watch } = require("yargs").argv;
  31. return watch ? gulpWatch(cssPath, postcssTask) : postcssTask();
  32. };
  33.  
  34. // 如果不想使用 parameter 控制 watch, 也可以定义 2 个 tasks, 调用变成 yarn run gulp watch 和 yarn run gulp build
  35. // exports.watch = function () {
  36. // gulpWatch(cssPath, postcssTask);
  37. // }
  38. // exports.build = postcssTask;

plugin 可以在 gulpfile.js 里, 也可以定义到 postcss.config.js. 但注意, postcss.config.js 这个 file 是一定要有的, 哪怕只是 module.exports = {}; 不然会报错

postcss.config.js

  1. module.exports = {}

Run Command

  1. "scripts": {
  2. "start": "gulp build" // or gulp watch or gulp --watch
  3. },

Gulp Sass

看这篇 CSS – Sass & SCSS

Gulp PostCSS + Sass

gulpfile.js

  1. const { src, dest, watch } = require("gulp");
  2. const sass = require("gulp-sass")(require("sass"));
  3. const sourcemaps = require("gulp-sourcemaps");
  4. const postcss = require("gulp-postcss");
  5. const postcssPresetEnv = require("postcss-preset-env");
  6.  
  7. function sassTask() {
  8. return src("./src/**/*.scss")
  9. .pipe(sourcemaps.init())
  10. .pipe(sass().on("error", sass.logError))
  11. .pipe(postcss([postcssPresetEnv({ stage: 1 })])) // 这里多了一个 postcss pipe
  12. .pipe(sourcemaps.write("."))
  13. .pipe(dest("src/"));
  14. }
  15.  
  16. exports.build = sassTask;
  17. exports.watch = function () {
  18. watch("./src/**/*.scss", sassTask);
  19. };

run command

  1. 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 的例子

  1. const { src, dest, parallel } = require("gulp");
  2. const svgSprite = require("gulp-svg-sprite");
  3.  
  4. function spriteSvgIconTask() {
  5. return src("src/icons/*.svg")
  6. .pipe(
  7. svgSprite({
  8. mode: {
  9. symbol: true,
  10. },
  11. })
  12. )
  13. .pipe(dest("src/icons/svg-icon-sprite"));
  14. }
  15.  
  16. function spriteSvgIconTask2() {
  17. return src("src/stooges-icons/*.svg")
  18. .pipe(
  19. svgSprite({
  20. mode: {
  21. symbol: true,
  22. },
  23. })
  24. )
  25. .pipe(dest("src/stooges-icons/svg-icon-sprite"));
  26. }
  27.  
  28. 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

  1. gulp spriteSvgIcon -f gulpfile.cjs

CSS – PostCSS的更多相关文章

  1. [译]PostCSS介绍

    PostCSS介绍 原文链接:http://www.smashingmagazine.com/2015/12/introduction-to-postcss/ 转自:http://www.zcfy.c ...

  2. boi剖析 - 基于webpack的css sprites实现方案

    本文是58到家前端工程化集成解决方案boi的博文系列之一.boi是基于webpack打造的一站式前端工程化解决方案,现已开源Github. 作为前端构建工具不可或缺的一个环节,自动生成css spri ...

  3. PostCss 从0开始

    PostCss 摘自 http://ju.outofmemory.cn/entry/215105 http://www.w3cplus.com/PostCSS/postcss-deep-dive-pr ...

  4. webpack(四)处理 css\less\sass 样式

    (一) 处理普通的.css 文件,需要安装 css-loader,style-loader .less 文件,需要安装 less-loader .sass 文件,需安装  less-loader np ...

  5. [翻译]纠正PostCSS的4大认识误区

    市面上已经有很多的前端工具,再来引入新的前端工具,价值大不大?这主要取决于,它是否给开发人员提供了新的功能,是否值得花时间和精力去学习和使用? PostCSS出现时有一个很有趣的现象.像sass和le ...

  6. webpack之postcss集成

    项目 为了 兼容各个浏览器,需要加各种 c3前缀,如果手动的加肯定 相对比较麻烦,但是现在有webpack,gulp之类的 工具可以自动给我们加上,可以说效率上加速不少.如果 配置中 做个happyp ...

  7. webpack css文件编译、自动添加前缀、剥离

    1.css文件编译 webpack默认只能编译js文件,引入css需要loader支持 // css文件写入js中 npm i style-loader -D // css文件loader npm i ...

  8. 处理CSS前缀问题的神器——AutoPrefixer

    众所周知为兼容所有浏览器,有的CSS属性需要对不同的浏览器加上前缀,然而有时添加一条属性,需要添加3~4条类似的属性只是为了满足浏览器的兼容,这不仅会增加许多的工作量. What is AutoPre ...

  9. postcss 运用及原理

    postcss 入坑指南 目标: 掌握 postcss 的使用 自定义 postcss 插件 掌握 stylelint 的使用 自定义 stylelint rule 扩展 css parser 解释器 ...

  10. webpack+react+antd 单页面应用实例

    React框架已经火了好长一段时间了,再不学就out了! 对React还没有了解的同学可以看看我之前的一篇文章,可以快速简单的认识一下React.React入门最好的实例-TodoList 自己从开始 ...

随机推荐

  1. 解决方案 | vba批量冻结首行,所有sheet一次性设置

    Sub FreezeTopRowAllSheets() Dim ws As Worksheet ' 遍历所有工作表 For Each ws In ThisWorkbook.Worksheets ' 激 ...

  2. Python 基于lxml.etree实现xpath查找HTML元素

    基于lxml.etree实现xpath查找HTML元素 By:授客 QQ:1033553122 #实践环境 WIN 10 Python 3.6.5 lxml-4.6.2-cp36-cp36m-win_ ...

  3. MySQL 纵表转横表查询实现

    纵表转横表查询实现 By:授客 QQ:1033553122 欢迎加入全国软件测试交流群:7156436 实践环境 MySQL 5.7 创建测试表 CREATE TABLE tb_test ( id I ...

  4. pytest批量执行多个测试文件(批量执行一个文件夹下的所有测试用例)

    图片 代码 #!/usr/bin/env python # @File : test_runall.py import pytest import os # path = os.path.dirnam ...

  5. Maven创建Web项目(idea)

    web项目创建 Web项目开发需要导入许多的第三方jar包,用Maven创建web项目就可以将这一操作免去. 本项目是在idea下创建的,idea自带Maven,如果还未了解Maven的同学可以看上一 ...

  6. 测试开发jmeter设置线程序号

    测试开发jmeter设置线程序号 ${__threadNum} 需要在请求的名称后面加上${__threadNum} 然后运行结果如下:

  7. gym中所有可以用的模拟环境

    python 代码: from gym import envs for env in envs.registry.all(): print(env.id) 打印出可用环境: Copy-v0 Repea ...

  8. X86架构CPU下Ubuntu系统环境源码编译pytorch-gpu-2.0.1版本

    本文操作步骤与 aarch64架构CPU下Ubuntu系统环境源码编译pytorch-gpu-2.0.1版本大致相同,只是CPU架构不同而已,因此这里只记录不同的地方. 重点: 一个个人心得,那就是要 ...

  9. python语言绘图:绘制一组正态分布图

    代码源自: https://github.com/PacktPublishing/Bayesian-Analysis-with-Python ============================= ...

  10. Inno Setup 出现 the drive or unc share you selected does not exist or is not accessible 解决记录

    背景 软件是使用Inno Setup的,且安装后,再次安装是默认安装到历史路径.一次用户电脑维修后,发现再次安装后报错 解决办法 取消自动安装到默认路径就好了~ UsePreviousAppDir=n ...