CSS预编译器三剑客及PostCSS

  • 时间:2018-07-12 22:38 作者:前端小学生 来源:前端小学生 阅读:1319
  • 扫一扫,手机访问
摘要:这篇文章包含两个部分,第一部分是个CSS预编译器:Sass、Less、Stylus,他们之间的比照,第二部分是现在大火的PostCSS。为什么会出现CSS预编译器这个东西呢?这就要谈到CSS的不足了:没有变量(新的规范已经支持了),不支持嵌套,编程可以力较弱,代码复使用性差。这些不足导致写出来的CS

这篇文章包含两个部分,第一部分是个CSS预编译器:Sass、Less、Stylus,他们之间的比照,第二部分是现在大火的PostCSS。

为什么会出现CSS预编译器这个东西呢?这就要谈到CSS的不足了:没有变量(新的规范已经支持了),不支持嵌套,编程可以力较弱,代码复使用性差。这些不足导致写出来的CSS维护性极差,同时包含大量重复性的代码;为了弥补这些不足之处,CSS预编译器应运而生。而谈到CSS预编译器,就离不开这三剑客Sass、Less、Stylus。历史上,最先登场的是Sass,由于出现最早,所以也是最完善的,有各种丰富的功可以;Less的出现伴随着Bootstrap的流行,因而也取得大量使用户;最后是Stylus,由TJ大神开发(敬大神),因为其简洁的语法,更像是一门编程语言,写起来非常Cool。所以下面我们来做一个简单的比照。

Less & SCSS:

.wrap {

display: block;

}

Sass:

.wrap

display: block

Stylus:

.wrap

display block

Sass最开始通过缩进,空格,换行的形式来控制层级关系,写过Python的同学肯定不会陌生,后来又支持了传统的类CSS语法的Scss。Less中规中矩,用CSS的风格,对新手非常友好,也利于现有项目的迁移。Stylus既能用Sass风格的语法来编写,也兼容CSS的风格。

这三者都支持变量的定义,而定义方式又各不相同:

Less:

@smallFont: 12px;

small {

font-size: @smallFont;

}

Sass:

$smallFont: 12px;

small {

font-size: $smallFont;

}

Stylus:

smallFont = 12px

small

font-size smallFont

需要注意的是:Stylus中公告的变量,假如变量名跟CSS中的字面值相同时,会覆盖CSS中的字面值。

有一个好玩的东西:相信大家平常都或者多或者少会接触到组件库,组件库的编写中会用到CSS的预编译器来编写样式,通过外部传入变量的方式来提供自己设置样式的功可以,就像Ant.design和ElementUI那样。这就涉及到CSS变量的作使用范围了,在这三种中预编译中,Sass/Stylus是相同的,Less是另一种情况,下面看实例:

Less:

@color: red;

.content-1 {

color: @color;

}

@color: black;

.content-2 {

color: @color;

}

/* 编译出来的CSS*/

.content-1 {

color: black;

}

.content-2 {

color: black;

}

Less中的变量,在公告中用时,假如出现屡次赋值的情况,其会取最后一次赋值的值,这也就是上面的.content-1, content-2中的color都是black的起因。基于Less中变量的这个特性,我们能很轻易的改变原有组件库或者者类库中变量的值,只要要在引入Less文件后,对特定的变量赋值就可。同时也会带来肯定的隐患:假如不同的组件库或者类库用了相同的变量名,那么就会出现覆盖的情况,所以应该采使用板块化的方式。

Sass:

$color: red;

.content-1 {

color: $color;

}

$color: black;

.content-2 {

color: $color;

}

Stylus:

color = red;

.content-1

color color

color = black;

.content-2

color color;

/* 编译出来的CSS*/

.content-1 {

color: red;

}

.content-2 {

color: black;

}

上面我们能看到,Sass/Stylus中的变量,假如出现屡次赋值的情况,其会取公告前面最近的一次赋值的值,这就是为什么.content-1的color为red,.content-2的color为black的起因。同时,在Sass/Stylus编写的不同组件库或者类库中的变量,不会出现冲突,但是这就为通过覆盖变量的值来自己设置样式提出了挑战,我们应该怎样做呢?考点来了,Sass/Stylus中提供了"不存在即赋值"的变量公告:

Sass:

$a: 1;

$a: 5 !default;

$b: 3 !default;

// $a = 1, $b = 3

Stylus:

a = 1

a := 5

b = 3

// a = 1, b = 3

细看代码,你肯定会明白:用"不存在即赋值"语法,编译器会检查前面能否定义了同名变量,假如没有定义,执行变量定义;假如前面定义了同名变量,则不会执行这个赋值的操作。因而,我们能在用了Sass/Stylus的组件库或者类库中用"不存在即赋值"的方式来定义变量,在引入之前定义好需要同名变量,就可以达到目的了。

同时,我们定义的变量不仅可以使用作CSS公告的值,同时也可以嵌套到选择器及属性中:

Less:

@prefix: ui;

@prop: background;

.@{prefix}-button {

@{prop}-color: red;

}

Sass:

$prefix: ui

$prop: background;

.#{$prefix}-button{

#{$prop}-color: red;

}

Stylus:

prefix = ui

prop = background

.{prefix}-button

{prop}-color red

变量相关的内容基本上覆盖到了,接下来就是样式的复使用了。提到样式复使用,必定会提到mixin和继承了。对于mixin,这三个预编译器也都有不同的实现方式:

Less:

.mixin-style(@color: red) {

color: @color;

}

.content {

.mixin-style(red);

}

Sass:

@mixin mixin-style {

color: red;

}

.content {

@include mixin-style;

}

Stylus:

mixin-style(color)

color color

.content

mixin-style(red) // or mixin-styls red 透明mixin

在Less中,能直接引入一个CSS的class作为mixin(这种方式非常不推荐), 同时也提供上面的可以够传入参数的mixin;Sass比较中规中矩,通过@mixin和@include的方式定义和引入mixin;Stylus不需要显示的公告mixin,同时还提供透明mixin的功可以,就像属性一样引入。

接下来就会讲到继承了,这其中,Sass/Stylus通过@extend关键字来继承样式,而Less通过伪类的方式来继承:

Sass/Stylus:

.message{

padding: 10px;

border: 1px solid #eee;

}

.warning{

@extend .message;

color: #e2e21e;

}

Less:

.message {

padding: 10px;

border: 1px solid #eee;

}

.warning {

&:extend(.message);

color: #e2e21e;

}

个中优劣,大家能自己评判。更多详细的比照,能查看顾轶灵大神的文章。

聊完了CSS预解决器,我们接下来聊聊大火的PostCSS。说到PostCSS,大家总会问,PostCSS是什么?这个问题,我们来看看官网对它的定义吧:

PostCSS is a tool for transforming styles with JS plugins. These plugins can lint your CSS, support variables and mixins, transpile future CSS syntax, inline images, and more.

所以我的了解是,PostCSS是一个用JS插件来转换样式的工具。PostCSS跟CSS预解决器的定位不同,看了前面的内容,大家都知道CSS预解决器的作使用是什么,而PostCSS的作使用主要有lint css,支持CSS Next语法,自动增加前缀等等功可以,通过插件,基本上能覆盖CSS 预解决器的功可以,同时实现多得多的预解决器实现不了的功可以。既然PostCSS这么牛逼,那我们来深入研究一下。

对于PostCSS,首先需要理解的有这么几个点:

  1. PostCSS不是CSS预解决器的替代品,尽管真的能使用PostCSS来替换掉。对于现有的项目,可以够很容易的用上PostCSS,无论你用的是哪一个预解决器或者者哪一个构建工具,都不会有太大的迁移成本。PostCSS的优势在于其丰富的插件生态,可以够覆盖开发中的方方面面,我们又可以够很容易的开发自己的插件。同时又由于PostCSS用Javascript,Javascript本身及其繁荣的生态,为PostCSS提供了更增强大的可以力。PostCSS中,最为大家所熟知的就是Autoprefix,同时Autoprefix在大量的预解决中用着。PostCSS依靠其现代的架构设计,甩掉了历史包袱,利使用其插件系统,可以够更加优雅强化CSS的健壮性

PostCSS架构大致如下图:

CSS预编译器三剑客及PostCSS

通过PostCSS将CSS转换成AST(笼统语法树),对应的是JavaScript对象;而后通过插件遍历AST,进行添加,删除,修改;最后再生成CSS文件,这就是整个流程,跟babel的架构非常类似。

其中的CSS解析成AST及AST序列化生成CSS,PostCSS都帮我们做好了,我们只要要关注在插件开发,及如何操作AST。

所以下面我们使用一个简单的例子来说明如何开发PostCSS的插件。有这么一个样式:

.content{

color: red;

}

假如我们检测到某个样式中有"color: red"这样一条样式规则,需要自动添加"background-color: red"这样一条规则。

PostCSS官方提供插件编写的模板,只要要将其下载下来:

git clone git@github.com:postcss/postcss-plugin-boilerplate.git

而后进入该文件夹的目录下,输入命令:

node start

这个时候会需要你输入少量信息,而后就会自动生成一个插件的模板文件夹,还是进入到这个对应的文件夹下,这个时候就可以看到熟习的package.json,index.js等文件,用npm安装了依赖之后即可以在index.js文件中编写插件的逻辑了。同样的,我们能在项目中通过npm安装任意依赖,而后在index.js中通过require引入,这就是背靠JavaScript的优势。

index.js默认的内容是这样的:

var postcss = require('postcss');

module.exports = postcss.plugin('postcss-practice', function (opts) {

opts = opts || {};

// Work with options here

return function (root, result) {

// Transform CSS AST here

};

});

编写出来的插件代码是这样的:

const postcss = require('postcss');

const postcss = require('postcss');

module.exports = postcss.plugin('postcss-practice', function (opts) {

opts = opts || {};

console.log(opts);

// Work with options here

return function (root) {

root.walkRules(rule => {

console.log(rule.selector);

rule.walkDecls(decl => {

if (

decl.prop === 'color' &&

decl.value === 'red'

) {

rule.append({

prop: 'background-color',

value: 'red'

});

}

});

});

};

});

非常简单,解释一下:root.walkRules会遍历每一个CSS规则,能通过rule.selector拿到每一组规则中的选择器,而后通过rule.walkDecls遍历每一组规则中的样式公告, 通过decl.prop,decl.value拿到样式公告中的属性和值。上面判断属性能否为'background-color'、值能否为'red',假如满足条件则向规则中插入一条新的样式公告(这里为了简单,没有考虑能否已经存在background-color公告)。

插件编写完了,样板项目中还包含index.test.js来测试能否插件能否正当,下面是编写的index.test.js中的测试代码:

var postcss = require('postcss');

var plugin = require('./index.js');

function run(input, output, opts) {

return postcss([ plugin(opts) ]).process(input)

.then(result => {

expect(result.css).toEqual(output);

expect(result.warnings().length).toBe(0);

});

}

// Write tests here

it('does something', () => {

return run('a{color: red;}',

'a{color: red;background-color: red;}', {});

});

而后是运行: "npm run test"的结果:

CSS预编译器三剑客及PostCSS

接下来即可以打包发布,而后在项目中安装用了,就像其余插件那样。PostCSS还提供了许多有使用的函数,帮助你操作AST,轻松完成开发。

  • 全部评论(0)
最新发布的资讯信息
【系统环境|】怎么做才能建设好外贸网站?(2023-12-20 10:05)
【系统环境|软件环境】梦幻仙域游戏攻略(2023-12-19 10:02)
【系统环境|软件环境】梦幻仙域游戏攻略(2023-12-19 10:02)
【系统环境|】卡帕部落揭秘潮玩新宠,探究玩法(2023-12-14 09:45)
【系统环境|数据库】 潮玩宇宙游戏道具收集方法(2023-12-12 16:13)
【系统环境|】如何开发搭建卡帕部落模式源码(2023-12-12 10:44)
【系统环境|】遥遥领先!青否数字人直播系统5.0发布,支持真人接管实时驱动!(2023-10-12 17:31)
【系统环境|服务器应用】克隆自己的数字人形象需要几步?(2023-09-20 17:13)
【系统环境|】Tiktok登录教程(2023-02-13 14:17)
【系统环境|】ZORRO佐罗软件安装教程及一键新机使用方法详细简介(2023-02-10 21:56)
手机二维码手机访问领取大礼包
返回顶部