PostCSS及其常用插件介绍

PostCSS及其常用插件介绍

前几天,PostCSS 6.0 分布了。

PostCSS 处理了很多你不必处理的乏味工作。它很巧妙的不同于预处理器,提供了可选的且更简洁的编程语言,来编译成 CSS,如 Sass、Less 与 Stylus。得出这个结论的部分原因是:

  • 它的名字。PostCSS 既能在预处理器将源代码编译成 CSS 之前也能在其之后对文件执行操作。
  • PostCSS 能替代你的预处理器。现在有很多插件实现了一些设计,如变量、 嵌套、mixins 以及 extends。

然而,虽然你可以构建自己的预处理器,但除非你想限制功能并加快编译速度,你没有别的该这么做的理由。就我个人而言,为增强 CSS,我使用 Sass,再加以 PostCSS 辅佐。没什么波澜,可能是对于大多数前端使用者来说没什么大的影响,因为通常大家都是使用其插件。

CSS 预处理器 和 CSS 后处理器

在说 PostCSS 之前,先了解一下 pre-processor 。

pre-processor(预处理器)

在写CSS的时候,经常会碰到这样的问题,比如说“变量”:

    h1{color:red;}.title{color:red;}.classA{color:red;}

如果有一天,我想要把颜色改用蓝色怎么办?你需要:查找 -> red ->替换 -> blue 。

先这种简单的 CSS 中,可能这并不繁琐,但是对于大型应用来说,可能是要摔键盘了。还有更多的问题,比如代码复用,嵌套,Mixins(混入)等等…

于是 Sass / Less就出现了,他们都是 CSS 的预处理器(pre-processor),看个简单的范例:

    $font-stack: Helvetica, sans-serif;$primary-color: #333;body {font: 100% $font-stack;color: $primary-color;}

这里用了变量功能,以后想要修改 CSS 直接改变量内容就好,不用在每一个地方都改了。像 Sass 这些预处理器,你要学一些新的语法,学一些新的表示方式,你就可以用这些新的语法写好一些看起来很像 CSS 但不是 CSS 的东西,然后把它编译成 CSS 。

post-processor(后处理器)

了解什么是 pre-processor 以后,来看看什么是 post-processor 。

post-processor(后处理器)最常见的例子就是这个了 CSS Prefixer 。

在写 CSS 的时候,会针对浏览器加上一些前缀,但是每次都这样写实在是很麻烦,官方范例,原本 CSS 是这样的:

    .my-class, #my-id {border-radius: 1em;transition: all 1s ease;box-shadow: #123456 0 0 10px;}

使用 CSS Prefixer 添加前缀后,

    .my-class, #my-id {-moz-border-radius: 1em;-webkit-border-radius: 1em;border-radius: 1em;-moz-transition: all 1s ease;-o-transition: all 1s ease;-webkit-transition: all 1s ease;transition: all 1s ease;-moz-box-shadow: #123456 0 0 10px;-webkit-box-shadow: #123456 0 0 10px;box-shadow: #123456 0 0 10px}

很简单,全帮你加好了,这就是后处理器(post-processor)

简单来说,预处理器( pre-processor )是你把一些长得很像 CSS 但不是 CSS 的东西丢给它,处理过后会给你编译过后的CSS,
而 CSS 再经过后处理器 ( post-processor ),透过一些规则帮它加上一些东西,最后产出完整的CSS文件!

或许你有一个疑问,预处理器( pre-processor )不是也可以完成这种工作吗?

sass代码:

    @mixin border-radius($radius) {-webkit-border-radius: $radius;-moz-border-radius: $radius;-ms-border-radius: $radius;border-radius: $radius;}.box { @include border-radius(10px); }

确实,在 Sass 里面,用 mixin 也可以达成加上前缀这样的目的。

那为什么要用 post-processor ?

后处理器有几个优点:

1.你可以写自己的插件:如果你选了 Sass ,你就必须接受 Sass 的一切,接受他的语法,要用就要用一整套 Sass,你不能只选择你要的某些功能,但是如果你用了 PostCSS ,你可以选择你自己想要的功能。更加确切的说,平时工作你基本不会直接去使用 PostCSS ,它的功能基本都是插件去完成的。 PostCSS 只是提供了一个环境。举例来说,加上前缀就是一个功能,或是让你可以用变量也是一个功能,你可以自己选择你想要的功能加入,而不是一用就要用一整套完整的方案,当然,你也可以用javascript写自己的plugin,解析 CSS 语法并且加入一些自己想要的东西。

2.用标准的 CSS 语法:前面有提过预处理器跟后处理器的差别,一个是写好 Sass(或其他的)丢进去,一个是把 CSS 加上一些东西之类丢出来,有些人相信将来的某一天,所有浏览器都会支援标准的 CSS ,例如说你不必再加上 -webkit- 之类的prefix
到了那一天,如果你是用 PostCSS ,你可以不做任何动作,直接拿原有的 CSS 就好,但如果你用的是 Sass 就没有办法这样
像是/ 这套,就提倡用「未来的 CSS 标准」写 CSS ,在现代先用后处理器的方式去产生可以跑的 CSS ,但是在未来的某一天,把那些 plugin 去除以后,你的 CSS 还是可以正常地跑出结果。

PostCSS 介绍

PostCSS 本身是一个功能比较单一的工具。它提供了一种方式用 JavaScript 代码来处理 CSS。它负责把 CSS 代码解析成抽象语法树结构(Abstract Syntax Tree,AST),再交由插件来进行处理。插件基于 CSS 代码的 AST 所能进行的操作是多种多样的,比如可以支持变量和混入(mixin),增加浏览器相关的声明前缀,或是把使用将来的 CSS 规范的样式规则转译(transpile)成当前的 CSS 规范支持的格式。从这个角度来说,PostCSS 的强大之处在于其不断发展的插件体系。目前 PostCSS 已经有 200 多个功能各异的插件。开发人员也可以根据项目的需要,开发出自己的 PostCSS 插件。

PostCSS 从其诞生之时就带来了社区对其类别划分的争议。这主要是由于其名称中的 post,很容易让人联想到 PostCSS 是用来做 CSS 后处理(post-processor)的,从而与已有的 CSS 预处理(pre-processor)语言,如 SASS 和 LESS 等进行类比。实际上,PostCSS 的主要功能只有两个:第一个就是前面提到的把 CSS 解析成 JavaScript 可以操作的 AST,第二个就是调用插件来处理 AST 并得到结果。因此,不能简单的把 PostCSS 归类成 CSS 预处理或后处理工具。PostCSS 所能执行的任务非常多,同时涵盖了传统意义上的预处理和后处理。PostCSS 是一个全新的工具,给前端开发人员带来了不一样的处理 CSS 的方式。

使用 PostCSS

PostCSS 一般不单独使用,而是与已有的构建工具进行集成。PostCSS 与主流的构建工具,如 Webpack、Grunt 和 Gulp 都可以进行集成。完成集成之后,选择满足功能需求的 PostCSS 插件并进行配置。下面将具体介绍如何在 Webpack、Grunt 和 Gulp 中使用 PostCSS 的 Autoprefixer 插件。

Gulp

为了在 Gulp 中使用 PostCSS,你需要建立你的项目并安装两个模块:

CommandLine 代码:

    npm initnpm install --save-dev gulp gulp-postcss

然后,你可以继续添加你需要的插件,如: autoprefixer 与 cssnano。

CommandLine 代码:

npm install --save-dev autoprefixer cssnano

你可以创建一个 gulpfile.js 文件。它定义了一个任务,加载 CSS 源文件然后通过 PostCSS 管道。插件以及任意所需的其它选项以一个数组传给 PostCSS。最终,CSS 文件被输出至目标文件。

Gulp.js 代码:

    // Gulp.js 配置var gulp = require('gulp'),postcss = require('gulp-postcss');// 应用 PostCSS 插件gulp.task('css', function() {return gulp.src('src/main.css').pipe(postcss([require('autoprefixer')({}),require('cssnano')])).pipe(gulp.dest('dest/main.css'));});

在控制台,可使用下面的命令运行该任务:

CommandLine 代码:

gulp css

现在我们只差一份方便的 PostCSS 插件列表了。

Webpack

Webpack 中使用 postcss-loader 来执行插件处理。在代码清单 1 中,postcss-loader 用来对.css 文件进行处理,并添加在 style-loader 和 css-loader 之后。通过一个额外的 postcss 方法来返回所需要使用的 PostCSS 插件。require(‘autoprefixer’) 的作用是加载 Autoprefixer 插件。

清单 1. 在 Webpack 中使用 PostCSS 插件

Webpack 代码:

    var path = require('path');module.exports = {context: path.join(__dirname, 'app'),entry: './app',output: {path: path.join(__dirname, 'dist'),filename: 'bundle.js'},module: {loaders: [{test:   /\.css$/,loader: "style-loader!css-loader!postcss-loader"}]},postcss: function () {return [require('autoprefixer')];}}

Grunt

Grunt 中使用 grunt-postcss 来集成 PostCSS。Grunt 中需要使用 grunt.loadNpmTasks 方法来加载插件,如代码清单 3 所示。

清单 3. 在 Grunt 中使用 PostCSS 插件

Grunt 代码:

    module.exports = function(grunt) {grunt.initConfig({postcss: {options: {processors: [require('autoprefixer')()]},dist: {src: 'app/**/*.css',expand: true,dest: 'dist'}}});grunt.loadNpmTasks('grunt-postcss');}

PostCSS 常用插件

Autoprefixer

Autoprefixer 是一个流行的 PostCSS 插件,其作用是为 CSS 中的属性添加浏览器特定的前缀。由于 CSS 规范的制定和完善一般需要花费比较长的时间,浏览器厂商在实现某个 CSS 新功能时,会使用特定的浏览器前缀来作为正式规范版本之前的实验性实现。比如 Webkit 核心的浏览器使用-webkit-,微软的 IE 使用-ms-。为了兼容不同浏览器的不同版本,在编写 CSS 样式规则声明时通常需要添加额外的带前缀的属性。这是一项繁琐而无趣的工作。Autoprefixer 可以自动的完成这项工作。Autoprefixer 可以根据需要指定支持的浏览器类型和版本,自动添加所需的带前缀的属性声明。开发人员在编写 CSS 时只需要使用 CSS 规范中的标准属性名即可。

安装 Autoprefixer。

CommandLine 代码:

npm install --save-dev autoprefixer

代码清单 4 中给出了使用 CSS 弹性盒模型的 display 属性声明。

清单 4. 标准的 CSS 弹性盒模型的 display 属性声明

CSS 代码:

    #content {display: flex;}

在经过 Autoprefixer 处理之后得到的 CSS 如代码清单 5 所示。

清单 5. 使用 Autoprefixer 处理之后的 CSS

CSS 代码:

    #content {display: -webkit-box;display: -webkit-flex;display: -ms-flexbox;display: flex;}

Autoprefixer 使用 Can I Use 网站提供的数据来确定所要添加的不同浏览器的前缀。随着浏览器版本的升级,浏览器在新版本中可能已经提供了对标准属性的支持,从而不再需要添加额外的前缀。Autoprefixer 可以配置需要支持的浏览器。如“last 2 versions”表示主流浏览器的最近两个版本,“ie 6-8”表示 IE 6 到 8,“> 1%”表示全球使用率大于 1%的浏览器版本。代码清单 6 中给出了配置 Autoprefixer 插件的示例。

清单 6. 配置 Autoprefixer 插件

JavaScript 代码:

    require('autoprefixer')({browsers: ['last 2 versions']})

Autoprefixer 除了添加所需要的属性名称前缀之外,还可以移除 CSS 代码中冗余的属性名称前缀。遗留 CSS 代码中可能包含由开发人员手动添加的旧版本的浏览器所支持的带前缀的属性名称。Autoprefixer 默认情况下会移除这些冗余的前缀。可以通过配置对象中的 remove 属性来配置该行为。

cssnext

cssnext 插件允许开发人员在当前的项目中使用 CSS 将来版本中可能会加入的新特性。cssnext 负责把这些新特性转译成当前浏览器中可以使用的语法。从实现角度来说,cssnext 是一系列与 CSS 将来版本相关的 PostCSS 插件的组合。比如,cssnext 中已经包含了对 Autoprefixer 的使用,因此使用了 cssnext 就不再需要使用 Autoprefixer。

自定义属性和变量

CSS 的层叠变量的自定义属性规范(CSS Custom Properties for Cascading Variables)允许在 CSS 中定义属性并在样式规则中作为变量来使用它们。自定义属性的名称以“–”开头。当声明了自定义属性之后,可以在样式规则中使用“var()”函数来引用,如代码清单 7 所示。

清单 7. CSS 自定义属性和变量

CSS 代码:

    :root {--text-color: black;}body {color: var(--text-color);}

在经过 cssnext 转换之后的 CSS 代码如代码清单 8 所示。

清单 8. 转换之后的 CSS 代码

CSS 代码:

    body {color: black;}

自定义选择器

CSS 扩展规范(CSS Extensions)中允许创建自定义选择器,比如可以对所有的标题元素(h1 到 h6)创建一个自定义选择器并应用样式。通过“@custom-selector”来定义自定义选择器。在代码清单 9 中,“–heading”是自定义选择器的名称,其等同于选择器声明“h1, h2, h3, h4, h5, h6”。

清单 9. 自定义选择器

CSS 代码:

    @custom-selector :--heading h1, h2, h3, h4, h5, h6;:--heading {font-weight: bold;}

经过 cssnext 处理之后的 CSS 如代码清单 10 所示。

清单 10. 转换之后的 CSS 代码

CSS 代码:

    h1,h2,h3,h4,h5,h6 {font-weight: bold;}

样式规则嵌套

样式规则嵌套是一个非常实用的功能,可以减少重复的选择器声明。这也是 SASS 和 LESS 等 CSS 预处理器流行的一个重要原因。CSS 嵌套模块规范(CSS Nesting Module)中定义了标准的样式规则嵌套方式。可以通过 cssnext 把标准的样式嵌套格式转换成当前的格式。CSS 嵌套规范中定义了两种嵌套方式:第一种方式要求嵌套的样式声明使用“&”作为前缀,“&”只能作为声明的起始位置;第二种方式的样式声明使用“@nest”作为前缀,并且“&”可以出现在任意位置。代码清单 11 中给出了两种不同声明方式的示例。

清单 11. 样式规则嵌套

CSS 代码:

    .message {font-weight: normal;& .header {font-weight: bold;}@nest .body & {color: black;}}

经过 cssnext 转换之后的 CSS 代码如代码清单 12 所示。

清单 12. 转换之后的 CSS 代码

CSS 代码:

    .message {font-weight: normal}.message .header {font-weight: bold;}.body .message {color: black;}

CSS 模块化

在编写 CSS 代码时会遇到的一个很重要的问题是 CSS 代码的组织方式。当项目中包含的 CSS 样式非常多时,该问题尤其突出。这主要是由于不同 CSS 文件中的样式声明可能产生名称冲突。现在的 Web 开发大多采用组件化的组织方式,即把应用划分成多个不同的组件。每个组件都可以有自己的 CSS 样式声明。比如,两个组件的 CSS 中可能都定义了对于 CSS 类 title 的样式规则。当这两个组件被放在同一个页面上时,冲突的 CSS 类名称可能造成样式的错乱。对于此类 CSS 类名冲突问题,一般的做法是避免全局名称空间中的样式声明,而是每个组件有自己的名称空间。BEM 通过特殊的命名 CSS 类名的方式来解决名称冲突的问题。两个不同组件中的标题的 CSS 类名可能为 component1__title 和 component2__title。

CSS 模块(CSS modules)并不要求使用 BEM 那样复杂的命名规范。每个组件可以自由选择最合适的简单 CSS 类名。组件的 CSS 类名在使用时会被转换成带唯一标识符的形式。这样就避免了名称冲突。在组件开发中可以继续使用简单的 CSS 类名,而不用担心名称冲突问题。代码清单 13 中给出了使用 CSS 模块规范的 CSS 代码。样式规则之前的“:global”表示这是一个全局样式声明。其他的样式声明是局部的。

清单 13. 使用 CSS 模块规范的 CSS 代码

CSS 代码:

    :global .title {font-size: 20px;}.content {font-weight: bold;}

经过转换之后的 CSS 样式声明如代码清单 14 所示。全局的 CSS 类名 title 保存不变,局部的 CSS 类名 content 被转换成_content_6xmce_5。这样就确保了不会与其他组件中名称为 content 的类名冲突。

清单 14. 转换之后的 CSS 代码

CSS 代码:

    .title {font-size: 20px;}._content_6xmce_5 {font-weight: bold;}

由于在组件的 HTML 代码中引用的 CSS 类名和最终生成的类名并不相同,因此需要一个中间的过程来进行类名的转换。对于 React 来说,可以使用 react-css-modules 插件;在其他情况下,可以使用 PostHTML 对 HTML 进行处理。postcss-modules 插件把 CSS 模块中的 CSS 类名的对应关系保存在一个 JavaScript 对象中,可以被 PostHTML 中的 posthtml-css-modules 插件来使用。

在代码清单 15 中,在使用 postcss-modules 插件时提供了一个方法 getJSON。当 CSS 模块的转换完成时,该方法会被调用。该方法的参数 json 参数表示的是转换结果的 JavaScript 对象。该对象被以 JavaScript 文件的形式保存到 cssModules 目录下,并添加了模块导出的逻辑。

清单 15. 保存 CSS 模块的输出文件

JavaScript 代码:

require('postcss-modules')({getJSON: function(cssFileName, json) {var cssName = path.basename(cssFileName, '.css');var jsonFileName = path.resolve(dist, 'cssModules', cssName + '.js');mkdirp.sync(path.dirname(jsonFileName));fs.writeFileSync(jsonFileName, "module.exports = " + JSON.stringify(json) + ";");}})

代码清单 16 中给出了使用 Gulp 的 gulp-posthtml 来处理 HTML 文件的任务。posthtml-css-modules 可以处理一个目录下的多个 CSS 模块输出文件。

清单 16. 使用 PostHTML 处理 HTML 里支持 CSS 模块

JavaScript 代码:

    gulp.task('posthtml', function() {var posthtml = require('gulp-posthtml');return gulp.src('app/**/*.html').pipe(posthtml([ require('posthtml-css-modules')(path.join(dist, 'cssModules')) ])).pipe(gulp.dest('dist/'));});

在 HTML 文件中使用“css-module”属性来指定对应的 CSS 类名。在代码清单 17 中,名称“header.content”的 header 表示的是 CSS 文件名,而 content 是该文件中定义的 CSS 类名。

清单 17. 使用 CSS 模块的 HTML 文件

HTML 代码:

<div css-module="header.content">Hello world</div>

在经过处理之后,得到的 HTML 内容如代码清单 18 所示。

清单 18. 转换之后的 HTML 文件

HTML 代码:

<div class="_content_6xmce_5">Hello world</div>

资源文件处理

在 CSS 中经常会需要引用外部资源,如图片和字体等。在 CSS 代码中处理这些资源时会遇到一些常见的问题,比如图片的路径问题,内联图片内容,生成图片 Sprites 等。对于这些问题,都有专门的 PostCSS 插件来提供所需的功能。

postcss-assets 插件用来处理图片和 SVG。在 CSS 声明中引用图片时,可以使用 resolve 加上图片路径的形式,如“resolve(‘logo.png’)”。在插件处理时,会按照一定的顺序在指定的目录中查找该文件,如果找到,会用图片的真实路径来替换。可以通过选项 loadPaths 来指定查找的路径,basePath 来指定项目的根目录。在 CSS 声明中,可以使用 width、height 和 size 方法来获取到图片的宽度、高度和尺寸。当需要内联一个图片时,可以使用 inline 方法。inline 会把图片转换成 Base64 编码的 data url 的格式,这样可以减少对图片的 HTTP 请求。代码清单 19 给出了使用示例。

清单 19. Postcss-assets 插件使用示例

JavaScript 代码:require('postcss-assets')({loadPaths: ['assets/images']})

代码清单 20 中给出了使用 resolve 的 CSS 样式声明。

清单 20. 使用 resolve 的 CSS 样式声明

CSS 代码:.logo {background-image: resolve('logo.png');}

代码清单 21 中给出了 cssnext 处理之后的 CSS 代码。

清单 21. 转换之后的 CSS 代码

CSS 代码:.logo {background-image: url('/assets/images/logo.png');}

PostCSS Assets

PostCSS Assets 提供了很多实用的图像处理函数:

CommandLine 代码:npm install --save-dev postcss-assets

它的选项包括:

  • 归约 URL: 通过给定文件名,PostCSS Assets 会使用根路径或完全合法的 URL 来替换 resolve(image)。
  • 处理尺寸: PostCSS Assets 会使用一个等价的像素值来替换 width(image), height(image) 或 size(image)。
  • 内联图像: PostCSS Assets 会使用 Base64 编码的字符串替换 inline(image)。
  • 清除缓存: PostCSS Assets 会给图像引用添加一个随机的查询字符串来确认加载的是最新的文件。

Rucksack

Rucksack 提供了很多函数,它的开发者宣称,它们会使 CSS 开发再次有趣起来。

CommandLine 代码:npm install --save-dev rucksack-css

它的选项包括:

  • 响应式的字体排版,仅需一个简单的 font-size: responsive 声明,就能够自动调整字体大小与行高。
  • 大量伪选择器,如 li:at-least(4),选择了任意含至少 4 个条目的列表。
  • 属性别名,如在你的 CSS 中使用 bg 代替 background,
  • 大量预定义的缓动函数。

Stylelint

Stylelint 基于 140 个规则报错,这些规则被设计用来捕获常见错误,实现样式协议并强制最佳实践。有很多选项可用来依你的喜好配置 Stylelint —— Pavels Jelisejevs 的文章使用 PostCSS 提升你的 CSS 质量带你走过搭建过程。

CSS MQPacker

MQPacker 在必要时会将你的媒体查询成一个规则:

CommandLine 代码:npm install --save-dev css-mqpacker

预处理器如 Sass 能在一个声明里使用媒体查询,很简单,如:

CSS 代码:.widget1 {width: 100%;@media (min-width: 30em) {width: 50%;}@media (min-width: 60em) {width: 25%;}}.widget2 {width: 100px;@media (min-width: 30em) {width: 200px;}}

这会编译成:

CSS 代码:.widget1 { width: 100%; }@media (min-width: 30em) {.widget1 { width: 50%; }}@media (min-width: 60em) {.widget1 { width: 25%; }}.widget2 { width: 100px; }@media (min-width: 30em) {.widget2 { width: 200px; }}

为了减小文件大小以及(尽可能)提升解析时间,MQPacker 会将多个声明打包到一个 @media 规则中,也就是

CSS 代码:.widget1 { width: 100%; }.widget2 { width: 100px; }@media (min-width: 30em) {.widget1 { width: 50%; }.widget2 { width: 200px; }}@media (min-width: 60em) {.widget1 { width: 25%; }}

可靠情报:确保你的代码中第一个媒体查询声明按照你所想的顺序定义了所有可能的选项,即使没有实际的不同。这能保证 MQPacker 会以正确的顺序定义规则。

MQPacker 也提供了选项来排序媒体查询与输出 sourcemap。

cssnano

cssnano 会压缩你的 CSS 文件来确保在开发环境中下载量尽可能的小。通过下面的命令安装它:

CommandLine 代码:npm install --save-dev cssnano

这个插件通过移除注释、空白、重复规则、过时的浏览器前缀以及做出其他的优化来工作,一般能减少至少 50% 的大小。还有很多其它选择,但 cssnano 是其中最好的一个。使用它!

PostCSS Sprites

Postcss-sprites 将扫描你CSS中使用的所有图像,自动生成优化的 Sprites 图像和 CSS Sprites 代码

CSS 代码:.rss{background: url(../img/icons/social-rss.png);}.twitter{background: url(../img/icons/social-twitter.png);}/* 将成为 */.rss{ background-image: url(../img/sprite.png); background-position: 0 0; width: 30px; height: 30px;}.twitter{ background-image: url(../img/sprite.png); background-position: -30px 0; width: 30px; height: 30px;}

当然,可以配置如何使用它们,并且告诉他忽略某些图像。

JavaScript 代码:require('postcss-sprites')({stylesheetPath: './css',spritePath: './img/sprite.png',retina: true,outputDimensions: true,filterBy: function(image){return /icons/gi.test(image.url)}}),

其他插件

还有其他实用的 PostCSS 插件可以在开发中使用。如 postcss-stylelint 用来检查 CSS 中可能存在的格式问题。cssnano 用来压缩 CSS 代码。postcss-font-magician 用来生成 CSS 中的 @font-face 声明。precss 允许在 CSS 中使用类似 SASS 的语法。

开发 PostCSS 插件

虽然 PostCSS 已经有 200 多个插件,但在开发中仍然可能存在已有插件不能满足需求的情况。这个时候可以开发自己的 PostCSS 插件。开发插件是一件很容易的事情。每个插件本质只是一个 JavaScript 方法,用来对由 PostCSS 解析的 CSS AST 进行处理。

每个 PostCSS 插件都是一个 NodeJS 的模块。使用 postcss 的 plugin 方法来定义一个新的插件。插件需要一个名称,一般以“postcss-”作为前缀。插件还需要一个进行初始化的方法。该方法的参数是插件所支持的配置选项,而返回值则是另外一个方法,用来进行实际的处理。该处理方法会接受两个参数,css 代表的是表示 CSS AST 的对象,而 result 代表的是处理结果。代码清单 22 中给出了一个简单的 PostCSS 插件。该插件使用 css 对象的 walkDecls 方法来遍历所有的“color”属性声明,并对“color”属性值进行检查。如果属性值为 black,就使用 result 对象的 warn 方法添加一个警告消息。

如果那还不够的话,你还可以用 JavaScript 开发你自己的 PostCSS 插件。PostCSS 文档讲解了 如何写一个插件 并提供了一份参考 API。

清单 22. PostCSS 插件示例

JavaScript 代码:var postcss = require('postcss');module.exports = postcss.plugin('postcss-checkcolor', function(options) {return function(css, result) {css.walkDecls('color', function(decl) {if (decl.value == 'black') {result.warn('No black color.', {decl: decl});}});};})

代码清单22中的插件的功能比较简单。PostCSS 插件一般通过不同的方法来对当前的 CSS 样式规则进行修改。如通过 insertBefore 和 insertAfter 方法来插入新的规则。

小结

对于 CSS 的处理一直都是 Web 开发中的一个复杂问题,其中一部分来源于 CSS 规范,一部分来源于不同浏览器实现带来的兼容性问题。PostCSS 为处理 CSS 提供了一种新的思路。通过 PostCSS 强大的插件体系,可以对 CSS 进行各种不同的转换和处理,从而尽可能的把繁琐复杂的工作交由程序去处理,而把开发人员解放出来。本文对 PostCSS 及其常用插件进行了详细介绍,希望可以帮助开发人员提高开发效率。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/782312.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于Tampermonkey 实现自动答题和视频播放

目录 一、环境准备 二、下载Tampermonkey 三、安装脚本 四、启用脚本 一、环境准备 微软自带的 edge 浏览器(电脑端) 二、下载Tampermonkey 安装地址&#xff1a;Tampermonkey 篡改猴(油猴脚本) 下载完成会在浏览器拓展中自动生成一个插件&#xff0c;此时点击管理拓展&…

WIFI驱动移植实验:WIFI从路由器动态获取IP地址与联网

一. 简介 前面两篇文章&#xff0c;一篇文章实现了WIFI联网前要做的工作&#xff0c;另一篇文章配置了WIFI配置文件&#xff0c;进行了WIFI热点的连接。文章如下&#xff1a; WIFI驱动移植实验&#xff1a;WIFI 联网前的工作-CSDN博客 WIFI驱动移植实验&#xff1a;连接WIF…

每日面经分享(Spring Boot: part2 DAO层)

1. Spring Boot DAO层的作用 a. 封装数据访问逻辑&#xff1a;DAO层的主要责任是封装与数据访问相关的逻辑。负责处理与数据库的交互&#xff0c;包括数据的增删改查等操作。通过将数据访问逻辑统一封装在DAO层中&#xff0c;可以提高代码的可维护性和可重用性。 b. 解耦业务逻…

pytest--python的一种测试框架--request请求加入headers

一、request headers中的cookie和session机制的作用与区别 Cookie 和 Session 是两种在客户端和服务器之间保持状态的技术。HTTP 协议本身是无状态的&#xff0c;这意味着服务器无法从上一次的请求中保留任何信息到下一次请求。Cookie 和 Session 机制就是为了解决这个问题。 …

Python算法学习

一、排序 排序算法是指将一组数据按照某种规则重新排列&#xff0c;使得数据呈现出递增或递减的顺序。常见的排序算法包括冒泡排序、选择排序、插入排序、快速排序、归并排序、堆排序等。 1.冒泡排序 解释&#xff1a; 冒泡排序通过不断交换相邻两个元素的位置&#xff0c;使…

dcat笔记

一&#xff0c;修改系统自带的表和页面 环境&#xff1a;laravel9dcat2php8.2 此处我想修改admin_users表&#xff0c;添加一个park_id 关联到parks表&#xff0c;须要修改管理员页面 使用继承重写的思路&#xff0c;最好不要直接去修改vendor包里面的dcat源码&#xff0c;只…

乐观锁的简单感悟

乐观锁&#xff08;Optimistic Locking&#xff09;是一种并发控制机制&#xff0c;用于解决多个线程或进程同时访问共享资源时可能发生的冲突问题。与悲观锁不同&#xff0c;乐观锁假设冲突很少发生&#xff0c;因此不会对整个操作过程进行严格的加锁。 乐观锁的实现方式通常…

Unity 通过鼠标移动和LineRenderer组件实现画线功能

在Unity中&#xff0c;使用LineRenderer组件可以在场景中绘制简单的线条&#xff0c;所以我们要实现通过鼠标移动来绘制线条的功能&#xff0c;可以使用LineRenderer组件实现。 要灵活进行绘制&#xff0c;那么就需要全程使用代码控制&#xff0c;包括线条的创建和基本属性设置…

KingSCADA|问题处理:数据输入后,数据已经写入,但SCADA界面显示为0问题。

哈喽&#xff0c;你好啊&#xff01;我是雷工&#xff01; 最近做KingSCADA项目遇到这么一个问题&#xff1a; KingSCADA系统和三菱的PLC通讯&#xff0c;当数值输入数据需要数据后&#xff0c;输入的数值点击确定按钮可以写入到PLC内&#xff0c;但是点完确定SCADA界面显示0&a…

神经网络 各个模块介绍(Pytorch 07)

一 网络层和块 单个神经网络&#xff08;1&#xff09;接受一些输入&#xff1b;&#xff08;2&#xff09;生成相应的标量输出&#xff1b;&#xff08;3&#xff09;具有一组相关 参数&#xff08;parameters&#xff09;&#xff0c;更新这些参数 可以优化某目标函数。 当…

CSS3 (一)

一、CSS3 2D转换 转换&#xff08;transform&#xff09;是CSS3中具有颠覆性的特征之一&#xff0c;可以实现元素的位移、旋转、缩放等效果。转换&#xff08;transform&#xff09;你可以简单理解为变形。 移动&#xff1a;translate 、旋转&#xff1a;rotate 、缩放&#xf…

MATLAB 点云随机渲染赋色(51)

MATLAB 点云随机渲染赋色(51) 一、算法介绍二、算法实现1.代码2.效果总结一、算法介绍 为点云中的每个点随机赋予一种颜色,步骤和效果如图: 1、读取点云 (ply格式) 2、随机为每个点的RGB颜色字段赋值 3、保存结果 (ply格式) 二、算法实现 1.代码 代码如下(示例):…

pytest--python的一种测试框架--pycharm创建项目并进行接口请求

前言 学习request的使用&#xff0c;在用之前&#xff0c;用官方文档提供的接口&#xff1a;https://api.github.com/events&#xff1b; ctrl鼠标左键可以进入被调用函数源码&#xff0c;可以看到第一个参数URL是必须参数&#xff0c;params是选填&#xff0c;**kwargs是关键…

嵌入式|蓝桥杯STM32G431(HAL库开发)——CT117E学习笔记15:PWM输出

系列文章目录 嵌入式|蓝桥杯STM32G431&#xff08;HAL库开发&#xff09;——CT117E学习笔记01&#xff1a;赛事介绍与硬件平台 嵌入式|蓝桥杯STM32G431&#xff08;HAL库开发&#xff09;——CT117E学习笔记02&#xff1a;开发环境安装 嵌入式|蓝桥杯STM32G431&#xff08;…

css3之2D转换transform

2D转换transform 一.移动&#xff08;translate)(中间用&#xff0c;隔开&#xff09;二.旋转&#xff08;rotate)&#xff08;有单位deg)1.概念2.注意点3.转换中心点&#xff08;transform-origin)&#xff08;中间用空格&#xff09;4.一些例子(css三角和旋转&#xff09; 三…

Spring Boot 使用详解

Spring Boot 使用详解 本节将详细介绍如何使用 Spring Boot。涵盖的主题包括构建系统、自动配置和如何运行应用程序。我们还将讨论一些 Spring Boot 最佳实践。尽管 Spring Boot 没有什么特别之处(它只是您可以使用的另一个库),但遵循以下一些建议会使您的开发过程更加轻松…

基于微信小程序医院挂号系统的设计与实现(论文+源码)_kaic

摘 要 进入21世纪网络和微信小程序得到了飞速发展&#xff0c;并和生活进行了紧密的结合。目前&#xff0c;网络的运行速度以达到了千兆&#xff0c;覆盖范围更是深入到生活中的脚脚落落。这就促使微信小程序的发展。微信小程序可以实现远程处理事务&#xff0c;远程提交工…

深度学习基础模型之Mamba

Mamba模型简介 问题&#xff1a;许多亚二次时间架构(运行时间复杂度低于O(n^2)&#xff0c;但高于O(n)的情况)&#xff08;例如线性注意力、门控卷积和循环模型以及结构化状态空间模型&#xff08;SSM&#xff09;&#xff09;已被开发出来&#xff0c;以解决 Transformer 在长…

mac怎么删除python

mac 默认安装了python2&#xff1b;自己后面又安装了python3&#xff1b;为了方便&#xff0c;现在想将python3换成Anaconda3。 Anaconda是一个开源的Python发行版本&#xff0c;其包含了conda、Python等180多个科学包及其依赖项。 Python3安装之后&#xff0c;在系统中不同目…

40个学习网站合集

1、Google&#xff1a;https://google.com 作为王牌浏览器&#xff0c;相比打开电脑就会进入谷歌浏览器&#xff0c;里面的谷歌搜索很好用。 在这里插入图片描述 2、CSDN— 开发者齐聚的网站&#xff1a;https://www.csdn.net/ CSDN不用多说&#xff0c;老牌专业 IT 技术社区&…