比神奇女侠还神奇的 postcss

陈大鱼头 ... 2021-8-3 Css
  • 前端
  • Css
  • Css预处理器
About 8 min

# postcss 是什么

官网 (opens new window) 上的介绍,它是一个 用 JavaScript 转换 CSS 的工具(A tool for transforming CSS with JavaScript)

与之类似的有 Sass (opens new window)Less (opens new window)Stylus (opens new window)CSS 预处理器 ,可以让我们通过更简便的方法去写 CSS

虽然利用 postcss 我们也可以写出变量 、函数、混合宏、扩展、条件语句、循环等 CSS 不支持(或者支持度)不高的语法,但是 postcss 本质还是一个 与业务无关的 CSS 工具 ,而实现以上诸多功能的还是依赖于社区上的各种 插件 (opens new window)

它的作用就如同 JS 里的 babel (opens new window) 一般。

# postcss 可以做什么

# 增强代码的可读性

利用从 Can I Use 网站获取的数据为 CSS 规则添加特定厂商的前缀。 Autoprefixer (opens new window) 自动获取浏览器的流行度和能够支持的属性,并根据这些数据帮你自动为 CSS 规则添加前缀。

示例如下:

// 输入
:fullscreen {
}

// 输出
:-webkit-full-screen {
}
:-ms-fullscreen {
}
:fullscreen {
}
1
2
3
4
5
6
7
8
9
10
11

# 将未来的 CSS 特性带到今天!

PostCSS Preset Env (opens new window) 帮你将最新的 CSS 语法转换成大多数浏览器都能理解的语法,并根据你的目标浏览器或运行时环境来确定你需要的 polyfills,此功能基于 cssdb (opens new window) 实现。

示例如下:

// 输入
body {
  color: lch(53 105 40);
}

// 输出
body {
  color: rgb(250, 0, 4);
}
1
2
3
4
5
6
7
8
9

# 终结全局 CSS

CSS 模块 (opens new window) 能让你你永远不用担心命名太大众化而造成冲突,只要用最有意义的名字就行了。

示例如下:

// 输入
.name {
  color: gray;
}

// 输出
.Logo__name__SVK0g {
  color: gray;
}
1
2
3
4
5
6
7
8
9

# 避免 CSS 代码中的错误

通过使用 stylelint (opens new window) 强化一致性约束并避免样式表中的错误。stylelint 是一个现代化 CSS 代码检查工具。它支持最新的 CSS 语法,也包括类似 CSS 的语法,例如 SCSS 。

示例如下:

// 输入
a {
  color: #d3;
}

// 控制台输出
app.css
2:10 Invalid hex color
1
2
3
4
5
6
7
8

# postcss 怎么用

我们可以以 webpack (opens new window) 为例看看如何进行配置。

首先就是安装基础插件:

npm install postcss-loader postcss --save-dev
or
yarn add postcss-loader postcss -D
1
2
3

然后在你的 webpack.config.js 里添加:

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ["style-loader", "css-loader", "postcss-loader"]
      }
    ]
  }
};
1
2
3
4
5
6
7
8
9
10

然后在根目录下创建文件 postcss.config.js ,内容如下:

module.exports = {
  plugins: []
};
1
2
3

现在就让我们为在 postcss 可以做什么 里提到的 4 个特性来添加相应的插件。

4 个特性对应的插件如下:

# autoprefixer(增强代码的可读性)

安装方式:

npm install autoprefixer --save-dev
or
yarn add autoprefixer -D
1
2
3

配置如下:

// postcss.config.js
const autoprefixer = require("autoprefixer");
module.exports = {
  plugins: [autoprefixer]
};
1
2
3
4
5

autoprefixer (opens new window) 是与 browserslist (opens new window) 进行关联, browserslist 就是一个告知打包工具项目将会运行的浏览器以及 node 平台,以此来创建相应的兼容性代码的工具。

所以我们可以在 package.json 里添加 browserslist 属性,或者在根目录添加 .browserslistrc 文件,示例如下(具体规则可根据项目情况来进行配置):

last 2 version
> 1%
IE 11
1
2
3

browserslist 的数据都是来自Can I Use (opens new window)的。

我们可以通过 https://browserslist.dev 来查看语句匹配情况。截图如下:

所以我们有:

// input
.example {
  display: grid;
  transition: all 0.5s;
  user-select: none;
  background: linear-gradient(to bottom, white, black);
}

// output
/*
* Prefixed by https://autoprefixer.github.io
* PostCSS: v7.0.29,
* Autoprefixer: v9.7.6
* Browsers: last 2 version
*/
.example {
  display: -ms-grid;
  display: grid;
  -webkit-transition: all 0.5s;
  transition: all 0.5s;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
  background: -webkit-gradient(
    linear,
    left top,
    left bottom,
    from(white),
    to(black)
  );
  background: linear-gradient(to bottom, white, black);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

我们可以通过 https://autoprefixer.github.io/ 在线看编译效果

# postcss-preset-env(将未来的 CSS 特性带到今天!)

安装方式:

npm install postcss-preset-env --save-dev
or
yarn add postcss-preset-env -D
1
2
3

配置如下:

// postcss.config.js
const postcssPresetEnv = require("postcss-preset-env");
module.exports = {
  plugins: [postcssPresetEnv(/* pluginOptions */)]
};
1
2
3
4
5

postcss-preset-env 可以让我们用一些浏览器支持率不高或者尚未支持的 CSS 属性

示例如下:

// input
:root {
  --fontSize: 1rem;
  --mainColor: #12345678;
  --secondaryColor: lab(32.5 38.5 -47.6 / 90%);
}
@custom-media --viewport-medium (width <= 50rem);

@media (--viewport-medium) {
  body {
    color: var(--mainColor);
    font-family: system-ui;
    font-size: var(--fontSize);
    line-height: calc(var(--fontSize) * 1.5);
    overflow-wrap: break-word;
    padding-inline: calc(var(--fontSize) / 2 + 1px);
  }
}

// output Stage 0 > 3%
:root {
  --fontSize: 1rem;
  --mainColor: rgba(18, 52, 86, 0.47059);
  --secondaryColor: rgba(102, 51, 153, 0.9);
}

html {
  overflow-x: hidden;
  overflow-y: auto;
  overflow: hidden auto;
}

@media (max-width: 50rem) {
  body {
    color: var(--mainColor);
    font-family: system-ui;
    font-size: var(--fontSize);
    line-height: calc(var(--fontSize) * 1.5);
    overflow-wrap: break-word;
    padding-left: calc(var(--fontSize) / 2 + 1px);
    padding-right: calc(var(--fontSize) / 2 + 1px);
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

我们可以通过 https://csstools.github.io/postcss-preset-env/ 在线看编译效果。

它可选的选项有 7 个,分别是:stage、features、browsers、insertBefore、insertAfter、autoprefixer、preserve、importFrom。

具体选项说明与示例可参考 https://github.com/csstools/postcss-preset-env 。

这里要着重分享两个选项:

# stage

在谈 stage 这个选项之前,首先我们得先知道一个概念—— cssdb

cssdbpostcss-preset-env 的实现基准,主要就是 CSS 的新功能功能及这些功能从提出到成为标准时所在的进程。

cssdbecma 一样,对新属性分了不同的进程,具体的进程如下:

Stage 0:脑袋风暴阶段。高度不稳定,可能会发生变化。

Stage 1:实验阶段。也非常不稳定,可能会发生变化,但是该提案已得到 W3C 成员的认可。

Stage 2:承认阶段。高度不稳定并且可能会发生变化,但是正在积极研究中。

Stage3:拥抱阶段。稳定且变化不大,此功能可能会成为标准。

Stage4:标准阶段。最终的解决方案,所有主流浏览器都支持。

所以 stage 这个配置的可选项就是 1、2、3、4 了。

# features

features 选项按 ID 启用或禁用特定的 polyfill 。启用就是 true

具体可参考 https://github.com/csstools/postcss-preset-env/blob/master/src/lib/plugins-by-id.js#L36

# css-modules(终结全局 CSS)

安装方式:

npm install postcss-modules --save-dev
or
yarn add postcss-modules -D
1
2
3

配置如下:

// postcss.config.js
const postcssModules = require("postcss-modules");
module.exports = {
  plugins: [postcssModules(/* pluginOptions */)]
};
1
2
3
4
5

css-modules 支持我们以模块化的形式来编写代码。示例如下:

// input
.grid {
  display: grid;
  grid: repeat(2, 240px) / auto-flow 320px;
  & > div {
    background-color: #8ca0ff;
    width: 200px;
    height: 200px;
    transition: 1s;
  }
}

// output
.demo__grid___2lKm5 {
  display: -ms-grid;
  display: grid;
  grid: repeat(2, 32vw) / auto-flow 42.667vw;
}
.demo__grid___2lKm5 > div {
  background-color: #8ca0ff;
  width: 26.667vw;
  height: 26.667vw;
  -webkit-transition: 1s;
  transition: 1s;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

其实在这里,如果不使用 postcss-modules ,也可以直接利用 css-loader 开启 css 模块化,具体配置如下:

// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          {
            loader: "css-loader",
            options: {
              modules: true,
              importLoaders: true,
              localIdentName: "[name]__[local]___[hash:base64:5]"
            }
          }
        ]
      }
    ]
  }
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# stylelint(避免 CSS 代码中的错误)

如果在 JS 中我们可以使用 eslint (opens new window) 进行代码检查一样,在 CSS 中我们也可以通过 stylelint (opens new window) 来进行代码检查。

安装方法:

npm install stylelint stylelint-config-standard --save-dev
or
yarn add stylelint stylelint-config-standard -D
1
2
3

配置如下:

// webpack.config.js
const StyleLintPlugin = require("stylelint-webpack-plugin");

module.exports = {
  plugins: [new StyleLintPlugin /* pluginOptions */()]
};
1
2
3
4
5
6

然后在根目录上创建 .stylelintrc 或者 stylelint.config.js 文件(具体文件可在 StyleLintPlugin 中配置),其内容如下:

{
    "extends": "stylelint-config-standard",
    "rules": {/* pluginOptions */}
}
1
2
3
4

所以当我们代码不规范时,就可以在命令行里看到类似的报错:

我们也可以在 编辑器 里找到对应的 stylelint 插件,从而进行 CSS 代码自动格式化。

# ying-template

ying-template (opens new window) 是鱼头在 GitHub 上开源的一个基于 webpack5 + typeScript4 + postcss8 的一个多页面脚手架,在最开始的版本中也引入了 sass、less ,不过后来因为 postcss 太香,就直接去除了 sass、less ,只留下 postcss 。

ying-template 目前已经在鱼头老东家的一个专利项目中投入了生产,而鱼头另一个开源库 ying-datastructures-algorithms (opens new window) (一个算法与数据结构 typescript 描述库)也在使用中,另外社区中也有一些小伙伴在项目中使用或借鉴了,各位有兴趣也可以 clone 下来看一下,可以感受下在 postcss 下的 css 是多么有魅力。

另外值得一提的是,除了上面介绍的几个基础插件之外,postcss 社区上也有许多有意思的插件,各位可以通过 https://www.postcss.parts/ 来选择自己所需要的插件进行使用。

# 参考资料

  1. ying-template (opens new window)
  2. PostCSS (opens new window)
  3. CSS 的未来已来 (opens new window)
  4. Autoprefixer (opens new window)
  5. Autoprefixer CSS online (opens new window)
  6. browserslist (opens new window)
  7. PostCSS Preset Env (opens new window)
  8. postcss.parts (opens new window)

# 后记

如果你喜欢探讨技术,或者对本文有任何的意见或建议,非常欢迎加鱼头微信好友一起探讨,当然,鱼头也非常希望能跟你一起聊生活,聊爱好,谈天说地。 鱼头的微信号是:krisChans95 也可以扫码关注公众号,订阅更多精彩内容。

https://bucket.krissarea.com/blog/base/qrcode-all1.png

Last update: June 25, 2023 00:16
Contributors: fish_head , 陈大鱼头