对PostCss及其插件的一些理解

1. CSS预处理器

CSS预处理器是一种专门的编程语言,用来为CSS增加一些编程特性(CSS本身不是编程语言)。不需要考虑浏览器兼容问题,因为CSS预处理器最终编译和输出的仍是标准的CSS样式。可以在CSS预处理器中使用变量、简单逻辑判断、函数等基本编程技巧。主流的CSS预处理器有SASS、LESS、Stylus。

2. CSS后处理器

CSS后处理器是对CSS进行处理,并最终生成CSS的预处理器,它属于广义上的 CSS 预处理器。

3. PostCSS(仓库地址)

  • 3.1 是什么?

    PostCSS 是一套利用JS插件实现的用来改变CSS的工具。可以理解为类似babel将ES6转为ES5。是一个平台、生态系统。它提供了API供开发者开发插件。这些插件能够支持变量和混合语法,转换未来CSS语法,内联图片等等。这里是常见的一些插件列表仓库

  • 3.2 工作原理

    • 将CSS解析成抽象语法树(AST,Abstract syntax tree)。
    • 将AST”传递”给任意数量的插件处理 。
    • 将处理完毕的AST树重新转换成字符串 。

    在PostCSS中有几个关键的处理机制:

    Source string → Tokenizer → Parser → AST → Processor → Stringifier

  • 3.3 如何理解Postcss处理的AST

    可以通过css AST查看可视化的语法树。
    CSS AST 节点主要有以下构造类组成:

    • Root: 根结点,整个处理过程基本上都在围绕着 Root,Commont,AtRule,Rule 都是它的子节点。
    • Commont: css 中的注释信息,注释的内容在 comment.text 下。
    • AtRule: 带@标识的部分,name 为标识名称,params 为标识参数。nodes 为内部包含的其他子节点,可以是 Commont,AtRule,Rule,这让我们可以自定义更多的规则。
  • Declaration:每个 css 属性以及属性值就代表一个 declaration

    3.3.1 Rule

    一个选择器代表一个Rule,选择器对应的样式列表 nodes 为 Declaration构造函数

    • raws
      • before 距离前一个兄弟节点之间的内容
      • between 选择器与 { 之间的内容
      • semicolon 最后一个属性是否带分号
      • after 最后一个属性 和 } 之间的内容
    • type 节点类型
    • nodes 子节点
    • source
      • start 开始位置
      • end 结束位置
      • selecter 选择器

    3.3.2 Declaration

    Declaration 是 css 样式属性,prop为样式属性,value为样式值。可给 Rule 手动添加样式属性,也可以修改prop,value。

PostCSS相关插件

1. autoprefixer

仓库地址

在开发过程中,为了兼容绝大部分浏览器,有的CSS属性需要对不同的浏览器加上前缀,因此有时候添加一条属性还需要添加3-4条类似的属性以满足不同浏览器的兼容性。autoprefixer会根据需要,使用Can I Use网站的数据自动添加浏览器厂商的前缀,减少我们的工作量。Vue-cli中默认开启了 autoprefixer。如果要配置目标浏览器,可使用 package.json 的 browserslist 字段。(通过修改Declaration的prop添加到选择器下)

2. postcss-preset-env

仓库地址

能够将最新的CSS语法转换成大多数浏览器都能理解的语法,是postcss-cssnext的替代者,后者已经被弃用了,有关更多描述我找到了作者留下的文章。需要注意的是,postcss-preset-env包含了autoprefixer,因此引入了postcss-preset-env就不需要再引入autoprefixer。

例如,它会将如下代码

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
/* 自定义媒体查询 */
@custom-media --viewport-medium (width <= 50rem);
/* 自定义选择器 */
@custom-selector :--heading h1, h2, h3, h4, h5, h6;

:root {
--mainColor: #12345678;
}

body {
color: var(--mainColor);
font-family: system-ui;
overflow-wrap: break-word;
}

:--heading {
background-image: image-set(url(img/heading.png) 1x, url(img/heading@2x.png) 2x);

@media (--viewport-medium) {
margin-block: 0;
}
}

a {
color: rgb(0 0 100% / 90%);
/* 选择器嵌套 */
&:hover {
color: rebeccapurple;
}
}

转化成:

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
:root {
--mainColor: rgba(18, 52, 86, 0.47059);
}

body {
color: rgba(18, 52, 86, 0.47059);
color: var(--mainColor);
font-family: system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Droid Sans, Helvetica Neue;
word-wrap: break-word;
}

h1, h2, h3, h4, h5, h6 {
background-image: url(img/heading.png);
}

@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
h1, h2, h3, h4, h5, h6 {
background-image: url(img/heading@2x.png)
}
}

@media (max-width: 50rem) {
h1, h2, h3, h4, h5, h6 {
margin-top: 0;
margin-bottom: 0;
}
}

a {
color: rgba(0, 0, 255, 0.9)
}

a:hover {
color: #639;
}

在该插件的官网,提供了四个阶段的css特性供我们选择,我们可以在该插件的配置项中修改,默认是stage 2。stage类似于Babel中使用的ECMAScript建议,这些stage意味着css成为标准所必须经历的步骤。

  • stage 0: Aspirational,提案或早期草稿。高度不稳定,可能会发生变化。

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

  • stage 2: 允许使用,但是高度不稳定,仍然在积极研究。

  • stage 3: Embraced,稳定且变化不大。此功能可能会成为标准配置。

  • stage 4: 标准,最终解决方案,被主流浏览器支持。

3. cssnano


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!