在前端界,有三大 CSS 预处理器,分别是 SASS(SCSS), Less, Stylus。 本文便总结下 Sass、Less CSS、Stylus这三个预处理器的区别和各自的基本语法。
我永远喜欢Stylus :>
什么是CSS预处理器
CSS 预处理器是一种语言用来为 CSS 增加一些编程的的特性,无需考虑浏览器的兼容性问题,例如你可以在 CSS 中使用变量、简单的程序逻辑、函数等等在编程语言中的一些基本技巧,可以让CSS 更见简洁,适应性更强,代码更直观等诸多好处。
基本语法比较
Sass和Less
首先 Sass 和 Less 都使用的是标准的 CSS 语法,因此如果可以很方便的将已有的 CSS 代码转为预处理器代码,默认 Sass 使用 .scss 扩展名,而 Less 使用 .Less 扩展名。
1
2
3
4/* style.scss or style.Less */
h1 {
  color: #0982C1;
}1
2
3/* style.Sass */
h1
  color: #0982c1
而 Stylus 支持的语法要更多样性一点,它默认使用 .styl 的文件扩展名。可以随意地书写。
1
2
3
4
5
6
7
8
9
10/* style.styl */
h1 {
  color: #0982C1;
}
/* 省略花括号 */
h1
  color: #0982C1;
/* 省略花括号和分号 */
h1
  color #0982C1
变量声明
- SassSass变量必须是以$开头的,然后变量和值之间使用冒号(:)隔开,和css属性是一样的。 
- LessLess变量都是用@开头的。 
- StylusStylus对变量是没有任何约束,可以是以$开头,或者任何的字符,而且与变量之间可以用冒号,空格隔开。 
嵌套
| 1 | section { | 
运算符
| 1 | body { | 
颜色函数
- Sass - 1 
 2
 3
 4
 5
 6
 7
 8- lighten($color, 10%); /* 返回的颜色在$color基础上变亮10% */ 
 darken($color, 10%); /* 返回的颜色在$color基础上变暗10% */
 saturate($color, 10%); /* 返回的颜色在$color基础上饱和度增加10% */
 desaturate($color, 10%); /* 返回的颜色在$color基础上饱和度减少10% */
 grayscale($color); /* 返回$color的灰度色*/
 complement($color); /* returns complement color of $color */
 invert($color); /* 返回$color的反相色 */
 mix($color1, $color2, 50%); /* mix $color1 with $color2 with a weight of 50% */
- Less - 1 
 2
 3
 4
 5
 6
 7- lighten(@color, 10%); /* 返回的颜色在@color基础上变亮10% */ 
 darken(@color, 10%); /* 返回的颜色在@color基础上变暗10%*/
 saturate(@color, 10%); /* 返回的颜色在@color基础上饱和度增加10% */
 desaturate(@color, 10%); /* 返回的颜色在@color基础上饱和度降低10%*/
 spin(@color, 10); /* 返回的颜色在@color基础上色调增加10 */
 spin(@color, -10); /* 返回的颜色在@color基础上色调减少10 */
 mix(@color1, @color2); /* 返回的颜色是@color1和@color2两者的混合色 */
- Stylus - 1 
 2
 3
 4- lighten(color, 10%); /* 返回的颜色在'color'基础上变亮10% */ 
 darken(color, 10%); /* 返回的颜色在'color'基础上变暗10% */
 saturate(color, 10%); /* 返回的颜色在'color'基础上饱和度增加10% */
 desaturate(color, 10%); /* 返回的颜色在'color'基础上饱和度降低10% */
css预处理器处理属性前缀
| 1 | @mixin border-radius($values) { | 
导入 (Import)
很多 CSS 开发者对导入的做法都不太感冒,因为它需要多次的 HTTP 请求。但是在 CSS 预处理器中的导入操作则不同,它只是在语义上包含了不同的文件,但最终结果是一个单一的 CSS 文件,如果你是通过 @ import “file.css”; 导入 CSS 文件,那效果跟普通的 CSS 导入一样。
1
2
3
4/* file.{type} */
body {
  background: #EEE;
}
| 1 | @import "reset.css"; | 
- 转译出的css1 
 2
 3
 4
 5
 6
 7@import "reset.css"; 
 body {
 background: #EEE;
 }
 p {
 background: #0982C1;
 }
混合(Mixins)
Mixins是预处器中的函数。当某段CSS样式经常要用到多个元素中,这样就需要重复的写多次。Mixins是一个公认的选择器,还可以在Mixins中定义变量或者是默认参数。
- Sass @mixin声明 @include调用 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15- @mixin error($borderWidth: 2px) { 
 border: $borderWidth solid #F00;
 color: #F00;
 }
 .generic-error {
 padding: 20px;
 margin: 4px;
 @include error(); //这里调用默认 border: 2px solid #F00;
 }
 .login-error {
 left: 12px;
 position: absolute;
 top: 20px;
 @include error(5px); //这里调用 border:5px solid #F00;
 }
- Less - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15- .error(@borderWidth: 2px) { 
 border: @borderWidth solid #F00;
 color: #F00;
 }
 .generic-error {
 padding: 20px;
 margin: 4px;
 .error(); //这里调用默认 border: 2px solid #F00;
 }
 .login-error {
 left: 12px;
 position: absolute;
 top: 20px;
 .error(5px); //这里调用 border:5px solid #F00;
 }
- Stylus 像函数一样 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15- error(borderWidth= 2px) { 
 border: borderWidth solid #F00;
 color: #F00;
 }
 .generic-error {
 padding: 20px;
 margin: 4px;
 error();
 }
 .login-error {
 left: 12px;
 position: absolute;
 top: 20px;
 error(5px);
 }
- example Sass3d文本 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13- @mixin text3d($color) { 
 color: $color;
 text-shadow: 1px 1px 0px darken($color, 5%),
 2px 2px 0px darken($color, 10%),
 3px 3px 0px darken($color, 15%),
 4px 4px 0px darken($color, 20%),
 4px 4px 2px #000;
 }
 h1 {
 font-size: 32pt;
 @include text3d(#0982c1);
 }
继承(Inheritance)
在多个元素应用相同的样式时,我们在CSS通常都是这样写:
1
2
3
4
5p,
ul,
ol {
  /* 样式写在这 */
}
- Sass和Stylus @extend - 1 
 2
 3
 4
 5
 6
 7
 8- .block { 
 margin: 10px 5px;
 padding: 2px;
 }
 p {
 @extend .block; /* 继承.block所有样式 */
 border: 1px solid #EEE;
 }
- Less LESS支持的继承和Sass与Stylus不一样,他不是在选择器上继承,而是将Mixins中的样式嵌套到每个选择器里面。这种方法的缺点就是在每个选择器中会有重复的样式产生。 - 1 
 2
 3
 4
 5
 6
 7
 8- .block { 
 margin: 10px 5px;
 padding: 2px;
 }
 p {
 .block; /* 继承 '.block'中的样式 */
 border: 1px solid #EEE;
 }
if语句
- Sass - 1 
 2
 3
 4
 5
 6- .mixin (@color) when (lightness(@color) > 30%) { 
 background-color: black;
 }
 .mixin (@color) when (lightness(@color) =<; 30%) {
 background-color: white;
 }
- Less - 1 
 2
 3
 4
 5
 6
 7- @if lightness($color) > 30% { 
 background-color: black;
 }
 @else {
 background-color: white;
 }
- Stylus - 1 
 2
 3
 4- if lightness(color) > 30% 
 background-color black
 else
 background-color white- loop
- Sass - 1 
 2
 3
 4
 5- @for $i from 1px to 3px { 
 .border-#{i} {
 border: $i solid blue;
 }
 }
- Less - 1 
 2
 3
 4
 5
 6
 7- .loop(@counter) when (@counter > 0){ 
 .loop((@counter - 1));
 .border-@{counter} {
 border: 1px * @counter solid blue;
 }
 }
- Stylus - 1 
 2
 3- for num in (1..3) 
 .border-{num}
 border 1px * num solid blue
作用域
- Sass Sass中不存在什么全局变量. - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10- $color: black; 
 .scoped {
 $bg: blue;
 $color: white;
 color: $color; /*白色*/
 background-color:$bg;
 }
 .unscoped {
 color:$color;/*白色*/
 }
- Less LESS中的作用域和其他程序语言中的作用域非常的相同,他首先会查找局部定义的变量,如果没有找到,会像冒泡一样,一级一级往下查找,直到根为止。 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10- @color: black; 
 .scoped {
 @bg: blue;
 @color: white;
 color: @color; /*白色*/
 background-color:@bg;
 }
 .unscoped {
 color:@color; /*黑色*/
 }
- Stylus Stylus虽然起步比较晚,但其作用域的特性和LESS一样,可以支持全局变量和局变量。会向上冒泡查找,直到根为止。 
总结
Less 从语言特性的设计到功能的健壮程度和另外两者相比都有一些缺陷,但用 Less 可以满足大多数场景的需求。 但相比另外两者,基于 Less 开发类库会复杂得多,实现的代码会比较脏,能实现的功能也会受到 DSL 的制约。 比 Stylus 语义更清晰、比 Sass 更接近 CSS 语法,使得刚刚转用 CSS 预编译的开发者能够更平滑地进行切换。 Sass 在三者之中历史最久,也吸收了其他两者的一些优点。 从功能上来说 Sass 大而全,语义明晰但是代码很容易显得累赘。 主项目基于 Ruby 可能也是一部分人不选择它的理由(Less 开始也是基于 Ruby 开发,后来逐渐转到 Less.js 项目中)。 Sass 有一个「事实标准」库——Compass,于是对于很多开发者而言省去了选择类库的烦恼,对于提升开发效率也有不小的帮助。 Stylus 的语法非常灵活,很多语义都是根据上下文隐含的。 基于 Stylus 可以写出非常简洁的代码,但对使用团队的开发素养要求也更高,更需要有良好的开发规范或约定。 总的来说,三种预处理器百分之七八十的功能是类似的。Less 适合帮助团队更快地上手预处理代码的开发,而 Sass 和 Stylus 的差异更在于口味。
 
        