文章目录
- PostCSS是什么
- postCSS的优点
- 补充:polyfill
- 补充:Stylelint
- PostCSS架构
- 概述
- 工作流程
- PostCSS解析方法
- PostCSS解析流程
- PostCSS插件
- 插件的使用
- 控制类插件
- 包类插件
- 未来的CSS语法相关插件
- 后备措施相关插件
- 语言扩展相关插件
- 颜色相关组件
- 图片和字体相关的类
- 网格(Grids)
- 优化相关插件
- 快捷方式
- 自定义PostCSS插件
- 查找节点
- 更改节点
- PostCSS自定义语法规则
postCSS是一个使用JS转换CSS的工具。
官网: https://postcss.nodejs.cn/
PostCSS是什么
PostCSS 是一个使用 JavaScript 插件转换 CSS
的工具。
功能:
- 检查(lint)你的 CSS
- 支持 CSS Variables 和 Mixins
- 编译尚未被浏览器广泛支持的先进的 CSS 语法,内联图片,等。
PostCSS 的核心 — 插件:
它提供了一个把 CSS 解析成抽象语法树(AST )的工具,以及一堆 API,来帮助开发者更方便的构建 PostCSS 插件
。开发者可以根据自己的需要,去挑选和自定义合适的 PostCSS 插件,来实现自己需要的功能。
例如,Post已存在的插件:
- Autoprefixer 插件:
自动为 CSS 属性添加私有前缀,以便于兼容不同的浏览器。 - cssnano 插件:
对CSS 代码进行压缩,以优化加载速度。
使用PostCSS插件可以按需为你的 CSS 流程增加功能。
postCSS的优点
- 提高代码可读性
将浏览器前缀添加到 CSS 规则中。Autoprefixer
基于当前浏览器流行度和属性支持的数据来为css样式应用前缀。 - 转换为通用的CSS
让你将现代 CSS 转换为大多数浏览器可以理解的内容,并使用cssdb
根据你的目标浏览器或运行时环境确定所需的polyfill
。 - 为css提供单独的命名空间,在不同的命名空间下css的类名可以一样
- 规范的css
使用stylelint
(css代码检查器)强制执行一致的约定,避免样式表中的错误。
补充:polyfill
Polyfill是一段代码
(通常是JavaScript),用来为旧的浏览器提供它原生不支持的较新的功能
。这样就可以在旧的浏览器上使用这些功能而不会出现问题。
例如,旧版本的浏览器可能并不支持 ECMAScript 2015(也可以说是ES6)的特性,比如Promise和Object.assign
。为了解决这个问题,开发者可以使用polyfill
,它是在加载JavaScript代码之前的一段代码
,这段代码会检查浏览器是否支持这些特性,若不支持则提供类似的功能。Polyfill允许开发者编写出最新的、最高级的代码,而不用担心兼容性问题。它会帮助你的网站或者Web应用在所有浏览器中保持一致的行为。
eg:手动编写Array.prototype.forEach
Array.prototype.forEach
方法在现代浏览器中是内置的,但是在一些老版本的浏览器中可能并不存在。所以我们可以编写一个 Polyfill 来“填充”这个漏洞:
if (!Array.prototype.forEach) {
Array.prototype.forEach = function(callback, thisArg) {
if (this == null) {
throw new TypeError('Array.prototype.forEach called on null or undefined');
}
var T, k;
var O = Object(this);
var len = O.length >>> 0;
if (typeof callback !== "function") {
throw new TypeError(callback + ' is not a function');
}
if (arguments.length > 1) {
T = thisArg;
}
k = 0;
while (k < len) {
var kValue;
if (k in O) {
kValue = O[k];
callback.call(T, kValue, k, O);
}
k++;
}
};
}
补充:Stylelint
Stylelint是强大的CSS检查器,可以帮助你避免错误并强制执行约定。
特性:
- 超过100条内置规则的现代CSS语法和功能。
- 支持插件,可以自定义规则
- 可以定制,以满足我们的具体需求
- 收到全球公司的信赖
PostCSS架构
概述
PostCSS不是像Sass或Less一样的样式处理器,他没有自定义的语法和语义,它实际上不是一种语言,而是一种CSS语法转换的工具。PostCSS与CSS一起使用,任何有效的CSS都可以由PostCSS处理。
PostCSS是CSS语法转换的工具,允许自定义CSS的语法
,这些语法可以被插件理解和转换。
工作流程
PostCSS解析方法
PostCSS是CSS的一个语法转换工具,对css代码进行解析。
常见的解析方法由两种:
-
使用一个从字符串转换成AST(抽象语法树)的文件进行解析。
Rework 分析器
就是使用这种方法解析的,缺点是如果代码库过大,代码会变得难以阅读并且速度非常慢。 -
拆分为词法分析
流程是源字符串-->标记-->AST(抽象语法树)
这是我们在PostCSS中的做法也是最流行的一种。 很多像@babel/parser
(Babel 背后的解析器)、CSSTree
这样的解析器都是这样写的。
这种方法将标记化与解析步骤分离,可以编写非常快的分词器(但有时难以阅读代码)和易于阅读(但速度慢)的解析器。
PostCSS解析流程
PostCSS的工作流程:
- 分词器:
如lib/tokenize.js
它接受 CSS 字符串并返回标记列表。
css:
.className { color: #FFF; }
使用分词器分词之后的标记是:
[
["word", ".className", 1, 1, 1, 10]
["space", " "]
["{", "{", 1, 12]
["space", " "]
["word", "color", 1, 14, 1, 18]
[":", ":", 1, 19]
["space", " "]
["word", "#FFF" , 1, 21, 1, 23]
[";", ";", 1, 24]
["space", " "]
["}", "}", 1, 26]
]
单个令牌表示为列表,并且 space 令牌没有位置信息。
- Parser解析器:
如lib/parse.js、lib/parser.js
Parse是传入语法分析的主要结构,解析器生成一个名为抽象语法树
(AST)的结构,稍后可以通过插件对其进行转换。
解析器对标记进行操作,而不是对源字符串进行操作。它主要使用 Tokenizer 提供的 nextToken 和 back 方法来获取单个或多个 token,然后构造 AST 的一部分,称为 Node
。
- 处理器
如 lib/processor.js
处理器是一个非常简单的结构,用于初始化插件
并运行语法转换
- 插件
插件可以是用户自定义的插件,也可以是PostCSS自带的插件,通过使用插件来为CSS添加特殊功能。
- 字符串化器
如lib/stringify.js
、lib/stringifier.js
Stringifier
是一个基类,他将修改的AST转换为纯CSS字符串。Stringifier从提供的Node开始遍历AST,并调用相应的方法生成它的原始字符串表示形式。最重要的方法是Stringifier.stringify
,他接受初始节点和分号指示符。
PostCSS插件
PostCSS所有插件:https://postcss.nodejs.cn/docs/postcss-plugins
插件的使用
PostCSS 是一个插件驱策的工具,它本身并没有提供很多功能。要想增加额外的功能,就需要需要下载并安装相应的插件,然后在PostCSS的配置文件·postcss.config.js·中引用。
如,使用autoprefixer
插件(autoprefixer
插件的作用是根据不同的浏览器为样式属性添加前缀)
- 下载插件
npm install autoprefixer --save-dev
- 在PostCSS的配置文件中引入
autoprefixer
postcss.config.js
module.exports = {
plugins: [
require('autoprefixer')
],
};
在这之后,autoprefixer 就会自动
在你的 CSS 规ules中添加供应商前缀
了。这些前缀是根据 Can I Use 网站的数据自动决定的。
例如,下面的 CSS:
a {
display: flex;
}
经过 autoprefixer 处理后,会变成:
a {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
}
这样一来,CSS 代码就可以在老版本的浏览器中也很好地运行了。
控制类插件
postcss-use
插件
作用: 允许你直接在CSS代码中通过@use
规则引入其他PostCSS插件,而无需在PostCSS的配置文件中进行配置。
使用:
下载
npm install postcss-use --save-dev
配置:
postcss.config.js
module.exports = {
plugins: [
require('postcss-use')()
]
};
引入其他插件
@use autoprefixer(browsers: ['last 2 versions']);
:fullscreen a {
display: flex;
}
就会根据不同的浏览器为fullscreen
添加前缀。
postcss-plugin-context
插件
作用: 为不同点css代码应用不同的PostCSS插件。
使用:
如,使用postcss-plugin-context
插件为不同css分别配置autoprefixer、cssnano
:
下载
npm install autoprefixer cssnano postcss-plugin-context --save-dev
配置postcss.config.js
:
module.exports = {
plugins: [
require('postcss-plugin-context')({
autoprefixer: require('autoprefixer'),
cssnano: require('cssnano')
}),
],
};
使用:
/* 为这部分 CSS 代码应用 autoprefixer 插件 */
@context autoprefixer {
.box {
display: flex;
}
}
/* 为这部分 CSS 代码应用 cssnano 插件 */
@context cssnano {
.title {
font-size: 20px;
margin-left: 10px;
margin-right: 10px;
}
}
包类插件
插件包需要下载才能使用,下载完之后在postcss
的配置文件中进行配置,构建的时候会自动使用。
postcss-utilities
:包括最常用的 mixin、快捷方式和辅助程序atcss
:根据特殊注释转换 CSS 的插件cssnano
:优化 CSS 大小以供生产使用的插件oldie
:可以转换css以兼容旧版Internet Explorer的插件rucksack
:包含通过新功能和快捷方式加速CSS开发的插件level4
:仅包含可让你编写CSS4而无需IE9回退的插件short
:添加并拓展了许多速记属性。styleint
:检查样式表的插件postcss-hamster
:用于垂直节奏、排版、模块化比例功能postcss-preset-env
:允许你将现代CSS转换为大多数浏览器可以理解的内容。postcss -ui-theme
:为你提供语法糖并允许你更改主题
未来的CSS语法相关插件
postcss-apply
:支持自定义属性集引用postcss-attribute-case-insensitive
:支持不区分大小写的属性postcss-bidirection
:使用单一语法生成从左到右和从右到左的样式。postcss-color-function
:支持转换颜色的函数postcss-color-gray
:支持 gray() 功能postcss-color-hex-alpha
:#rrggbbaa 和 #rgba 表示法。postcss-extend
:递归地支持规则和占位符的规范,近似@extend
postcss-pseudo-is
:将is
属性转换为更兼容的CSSpostcss-selector-not
:将CSS4:not()转换为CSS3的 :not()
后备措施相关插件
postcss-color-rgba-fallback
:将 rgba() 转换为十六进制。postcss-epub
:将-epub-
前缀添加到相关属性中。postcss-fallback
:添加了fallback
函数以避免重复声明postcss-filter-gradient
:为旧版IE添加了渐变滤镜postcss-flexibility
:为Flexibility polyfill
添加-js-
前缀。postcss-hash-classname
:将哈希字符串添加到你的css类名
中。—— vue的scopedpostcss-mqwidth-to-class
:将最小/最大宽度媒体查询转换为类。postcss-opacity
:为 IE8 添加了不透明度过滤器。postcss-opacity-percentage
:将 CSS4 基于百分比的opacity
值转换为浮点值。postcss-page-break
:将page-break-
后备添加到break-
属性。postcss-pseudoelements
:将::
转换成:
钻则其一兼容IE8postcss-replace-overflow-wrap
:用 word-wrap 替换 overflow-wrappostcss-vmin
:为 IE9 中的 vmin 单元生成 vm 后备。autoprefixer
:使用 Can I Use 中的数据为你添加浏览器前缀。postcss-pie
:使 IE 具备了几个最有用的 CSS3 装饰功能。cssgrace
:为IE和其他旧浏览器提供各种辅助程序和转义CSS3。pixrem
:为 rem 单位生成像素回退。webp-in-css
:在 CSS 中使用 WebP 背景图片。postcss-clamp
:将clamp()变换为min/max
的组合。postcss-spring-easing
:用生成的linear()
函数替换spring()
语言扩展相关插件
postcss-aspect-ratio
:将元素的尺寸固定为纵横比。postcss-atroot
:将规则直接放置在根节点处。postcss-click
:允许使用:click
伪类并在 JavaScript 中实现它。postcss-conditionals
:添加@if
语法postcss-css-variables
:支持使用 W3C 类似语法的选择器变量和 at 规则。postcss-define-property]
:定义属性快捷方式。postcss-for
:添加@for
循环csstyle
:将组建工作流程添加到样式中
颜色相关组件
post-ase-colors
: 用从 ASE 调色板文件读取的值替换颜色名称。postcss-brand-colors
:在brand-colors
模块中插入公司品牌颜色。postcss-color-mix
:将两种颜色混合在一起。postcss-color-short
:添加了简写颜色声明。postcss-theme-colors
:添加带有颜色组的深色和浅色主题。postcss-rgba-hex
: 将 rgba 值转换为 hex 类似物。postcss-get-color
:从图片中获取突出的颜色。postcss-randomcolor
:支持使用随机颜色的功能。
图片和字体相关的类
postcss-assets
:简化 URL、插入图片尺寸和内联文件postcss-assets-rebase
:重新设定url()
的资源基础。postcss-copy-assets
:将相对url()
引用的资源复制到构建目录中。postcss-data-packer
:将嵌入的Base64 数据
移动到单独的文件中。postcss-image-set
:将background-image
添加到image-set()
的第一张图片。[postcss-foft-classes]
:为使用 Web 字体的块添加了保护类,以实现更好的字体加载策略。postcss-placehold
: 可以轻松放置占位符图片。postcss-svg
:将内联 SVG 插入 CSS 并允许管理它的颜色。postcss-svgo
:通过 SVGO 处理内联 SVG。postcss-url
:变基或内联 url()。postcss-urlrebase
:将 url() 重新设置为给定的根 URL。postcss-write-svg
:在 CSS 中编写内联 SVG。
网格(Grids)
postcss-grid
:添加了语义网格系统。postcss-grid-kiss
:将ASCII-art 网格
转换为 CSS 网格布局。postcss-grid-system
:基于固定的列宽创建网格。postcss-grid-fluid
:创建流体网格。postcss-layout
:是一些常见 CSS 布局模式和网格系统的插件。
优化相关插件
postcss-import
:内联@import
规则引用的样式表。postcss-calc
:将calc()
简化为值。postcss-nested-import
: 在嵌套规则块内内联 @import 规则引用的样式表。postcss-partial-import
:内联标准导入和类似Sass
的部分。postcss-remove-root
:从样式表中删除 :root 的所有实例。postcss-zindex
:重新设置正 z-index 值的基准。css-byebye
: 删除了你不需要的 CSS 规则。postcss-no-important
:删除声明!important。
快捷方式
postcss-alias
:为属性创建较短的别名。postcss-border
:在 border 属性中添加了所有边框的宽度和颜色的简写。postcss-button
:创建按钮。postcss-center
:居中元素。postcss-circle
:插入一个带有颜色的圆圈。postcss-verthorz
:添加垂直和水平间距声明。font-magician
:生成 CSS 中所需的所有 @font-face 规则
自定义PostCSS插件
大多数 PostCSS 插件都会做两件事:
- 在 CSS 中查找某些内容(例如,will-change 属性)。
- 更改找到的元素(例如,在 will-change 之前插入 transform: translateZ(0) 作为旧浏览器的填充)。
查找节点
PostCSS 将 CSS 解析为节点树(我们称之为 AST
)。 这棵树可能包含:
- Root:
树顶部的节点
,代表 CSS 文件。 - AtRule: 语句以
@
开头,如 @charset “UTF-8” 或 @media (screen) {}。 - Rule: 内部带有
声明的
选择器。 例如 input, button {}。 - Declaration:
键值对
,如 color: black; - Comment:
独立注释
。 选择器内的注释、规则参数和值存储在节点的 raws 属性中。
可以在插件对象中添加方法
来查找具有特定类型的所有节点:
module.exports = (opts = {}) => {
return {
postcssPlugin: 'PLUGIN NAME',
Once (root) {
每个文件调用一次,因为每个文件都有一个根
},
Declaration (decl,{Rule}) {
// 所有声明节点
}
}
}
module.exports.postcss = true
所添加的方法都是插件事件,更多事件可以戳这里
插件时间的第二个参数是节点的创建者。
更改节点
当找到正确的节点时,需要更改它们或插入/删除周围的其他节点。
PostCSS 节点有一个类似 DOM
的 API 来转换 AST。 PostCSS 节点具有四处移动(如 Node#next 或 Node#parent
)、查看子节点(如 Container#some
)、删除节点
或在内部添加新节点
的方法。如果添加了新节点,复制 Node#source
以生成正确的源映射非常重要。
更改节点的操作需要在插件事件函数中进行编写:
Declaration (node, { Rule }) {
let newRule = new Rule({ selector: 'a', source: node.source })
node.root().append(newRule)
newRule.append(node)
}
eg:编译写个使字体变红的插件:
const plugin = () => {
return {
postcssPlugin: 'to-red',
Rule (rule) {
console.log(rule.toString())
},
Declaration (decl) {
console.log(decl.toString())
decl.value = 'red'
}
}
}
plugin.postcss = true
await postcss([plugin]).process('a { color: black }', { from })
// => a { color: black }
// => color: black
// => a { color: red }
// => color: red
PostCSS自定义语法规则
PostCSS可以转换任何语法的样式,而不仅限于CSS。通过编写自定义语法,你可以将样式转换为任何所需的格式。
自定义语法规则包含解析器和字符串生成器:
- 解析器:将输入字符串解析到节点树。
解析器包含两个步骤:分词标记数组、读取标记数组并构建树 - 字符串转化器:通过节点树生成输出字符串。
语法 API 是一个非常简单的普通对象,具有 parse 和 stringify 函数
,自定义语法规则格式:
module.exports = {
parse: require('./parse'),
stringify: require('./stringify')
}
解析器API,有两个参数:第一个参数是一个css字符串,第二个参数是一个函数接收带有 PostCSS 选项的对象,解析器API的返回值是一个函数,返回[Root]或[Document]
节点的函数。
const postcss = require('postcss')
module.exports = function parse (css, opts) {
const root = postcss.root()
// 处理css为dom节点,添加到root节点中
//返回root节点
return root
}
Stringifier API 比解析器 API 稍微复杂一些。 PostCSS 生成源映射
,因此字符串生成器不能只返回字符串。 它必须将每个子字符串与其源节点链接起来
。
Stringifier 是一个接收 [Root] 或[Document] 节点
和构建器回调
的函数。 然后它使用每个节点的字符串和节点实例调用构建器。
module.exports = function stringify (root, builder) {
// Some magic
const string = decl.prop + ':' + decl.value + ';'
builder(string, decl)
// Some science
};