谈谈CSS预处理器

在写CSS的时候咱们会发现,为了兼容浏览器等缘由,咱们每每须要写不少冗余的代码,CSS预处理器就是为了解决CSS的这些问题,简化CSS代码的编写。php

目前最主流的CSS预处理器是LESS、SASS和Stylus,最近花了几天时间学习并使用了它们,因而就想对这三个预处理器作个比较。根据这三种语言的特性,主要从一下几个方面进行讨论:css

  1. 基本语法web

  2. 变量编程

  3. 嵌套浏览器

  4. 混入(mixin)sass

  5. 继承less

  6. 函数编程语言

  7. @import函数

  8. 运算符学习

  9. 逻辑控制

基本语法

LESS的基本语法和CSS差很少,SASS和Stylus均可以利用缩进代替花括号,而且空格有重要的意义。SASS保存为".sass"是缩进格式,保存为".scss"是非缩进格式。SASS通常使用".scss"扩展名。LESS的扩展名为".less",Stylus的扩展名为".styl"。

注意:SASS依赖于Ruby,安装前必须先安装Ruby。

LESS & SCSS:

ul {
    list-style: none;
}

SASS:

ul
    list-style: none

Stylus:

ul
    list-style none

注意:如下SASS代码都以扩展名为".scss"的方式书写。

变量

CSS预处理器中能够定义变量,而且能够在样式表中使用,变量类型没有限制,这样就能够必定程度上减小CSS中没法避免的重复问题。

LESS变量名必须以@符号开头,变量名和变量值之间以冒号隔开。有个问题是@规则在CSS中算是一种原生的扩展方式,变量名用@开头极可能会和之后CSS中的新@规则冲突。

@orange: #feb914;
header {
    background-color: @orange;
}

SASS变量名必须以$开始,变量名和变量值之间以冒号隔开。

$orange: #feb914;
header {
    background-color: $orange;
}

Stylus对变量名没有任何限定,变量名与变量值之间能够用冒号、空格和等号隔开。

bgorange = #feb914;
header
    background-color bgorange

上面三种不一样的写法都会产生相同的结果:

header {
    background-color: #feb914;
}

Stylus还有一个独特功能,它不须要分配值给变量就能够定义引用属性。以下:

#logo
    position: absolute
    top: 50%
    left: 50%
    width: w = 150px
    height: h = 80px
    margin-left: -(w / 2)
    margin-top: -(h / 2)
#logo
    position: absolute
    top: 50%
    left: 50%
    width: 150px
    height: 80px
    margin-left: -(@width / 2)
    margin-top: -(@height / 2)

变量做用域

三种预处理器中定义的变量都是有做用域的,查找变量的顺序是先在局部定义中查找,若是找不到,则逐级向上查找。

若是咱们在代码中重写某个已经定义的变量,Less的处理逻辑和其余两个有区别。Less中,这个行为叫懒加载(Lazy Loading)。注意Less中全部变量的计算,都是以这个变量最后一次被定义的值为准。

LESS:

@size: 40px;
.content {
    width: @size;
}
@size: 60px;
.container {
    width: @size;
}

编译输出为:

.content {
    width: 60px;
}
.container {
    width: 60px;
}

在SASS中状况以下:

$size: 40px;
.content {
    width: $size;
}
$size: 60px;
.container {
    width: $size;
}

编译输出为:

.content {
    width: 40px;
}
.container {
    width: 60px;
}

Stylus和SASS行为相同,变量的计算以变量最近一次的定义为准。

变量插值

预处理器中定义的变量不只能够用做属性值,还能够用做选择器,属性名等,这就是变量插值。

变量名插值

Less中支持以@@var的形式引用变量,即该变量的名字是由@var的值决定的。

选择器插值

以类选择器为例

LESS:

@way: new;
.@{way}-task {
    font-size: 18px;
}

SASS:

$way: new;
.#{$way}-task {
    font-size: 18px;
}

Stylus:

way: new;
.{way}-task
    font-size 18px

解析结果都是:

.new-task {
    font-size: 18px;
}

注意:在Less中,经过选择器插值生成的规则没法被继承。

@import插值

Sass中只能在使用url()表达式时进行变量@import插值:

$device: mobile;
@import url(styles.#{$device}.css);

Less中能够在字符串中进行插值:

@device: mobile;
@import "styles.@{device}.css";

Stylus中没有@import插值,可是能够利用其字符串拼接的功能实现:

device = "mobile"
@import "styles." + device + ".css"

属性名插值

三个预处理器均支持属性名插值,使用方式且和上述插值相似。

嵌套

若是须要在相同的父元素中选择多个子元素,须要一遍又一遍地写父元素,若是用CSS预处理器就能够不用重复写父元素,而且父元素和子元素的关系一目了然。

三种预处理器的嵌套语法是一致的,引用父级选择器的标记&也相同。除了&,Sass和Stylus还分别用@at -root和"/"符号做为嵌套时根规则集的选择器引用。首先以LESS为例讨论嵌套语法:

#sort {
    margin-top: 24px;
    ul {
        margin-left: 8px;
        line-height: 36px;
        vertical-align: middle;    
    }
}
input {
    width: 80px;
    &:-ms-input-placeholder {
    font-size: 16px;
    color: @white;
    }
}

编译结果为:

#sort {
    margin-top: 24px;
}
#sort ul {
    margin-left: 8px;
    line-height: 36px;
    vertical-align: middle;
}
input {
    width: 80px;
}
input:-ms-input-placeholder {
    font-size: 16px;
    color: @white;
}

SASS还提出了属性嵌套,属性嵌套指的是有些属性拥有相同的开始单词,如border-width,border-color都是以border开头。官网的实例以下:

.fakeshadow {
    border: {
        style: solid;
        left: {
            width: 4px;
            color: #888;
        }
        right: {
            width: 2px;
            color: #ccc;
        }
    }
}

生成的CSS为:

.fakeshadow {
    border-style: solid;
    border-left-width: 4px;
    border-left-color: #888;
    border-right-width: 2px;
    border-right-color: #ccc; 
}

混入(mixin)

mixins有点像C语言中的宏,当某段CSS常常须要在多个元素中使用时,能够为这些共用的CSS定义一个mixin,而后只须要在须要引用这些CSS地方调用该mixin便可。

三种预处理器的mixin使用方式的差别比较大,下面分别说明。

LESS混入方式以下:

.my-mixin {
    color: black;
}
.my-other-mixin() {
    background: white;
}
.my-hover-mixin() {
    &:hover {
        border: 1px solid red;
  }
}
.border-radius(@radius: 5px) {
    -webkit-border-radius: @radius;
        -moz-border-radius: @radius;
            border-radius: @radius;
}
.class {
    .my-mixin;
    .my-other-mixin;
}
button {
    .my-hover-mixin();
}
#header {
    .border-radius(4px);
}
.button {
    .border-radius;
}

编译输出为:

.my-mixin {
    color: black;
}
.class {
    color: black;
    background: white;
}
button:hover {
    border: 1px solid red;
}
#header {
    -webkit-border-radius: 4px;
        -moz-border-radius: 4px;
            border-radius: 4px;    
}
.button {
    -webkit-border-radius: 5px;
        -moz-border-radius: 5px;
            border-radius: 5px;    
}

LESS的mixin须要注意的是同名的mixin不是后面的覆盖前面的,而是会累加输出。这就会产生一个问题,若是存在和mixin同名的class样式,而且mixin没有参数,则在调用时会把对应的class样式一块儿输出,这显然不是咱们所须要的。

SASS的mixin用法以下:

@mixin center-block {
    margin-left:auto;
    margin-right:auto;
}
.demo{
    @include center-block;
}
@mixin horizontal-line($border:1px dashed #ccc, $padding:10px){
    border-bottom:$border;
    padding-top:$padding;
    padding-bottom:$padding;  
}
.imgtext-h li{
    @include horizontal-line(1px solid #ccc);
}

编译结果为:

.demo{
    margin-left:auto;
    margin-right:auto;
}
.imgtext-h li {
    border-bottom: 1px solid #cccccc;
    padding-top: 10px;
    padding-bottom: 10px;
}

Sass用@mixin和@include两个指令清楚地说明了mixin的定义和引用方式。

Stylus的mixin和Sass的相似:

border-radius(n)
    -webkit-border-radius n
    -moz-border-radius n
    border-radius n
form input[type=button]
    border-radius 5px

继承

继承其实和混入的做用差很少,那为何还须要继承呢?混入确实很好用,可是若是多个地方都混入一样的代码,会形成代码的重复。例如:

.block {
    margin: 10px 5px;
    padding: 2px;
}
p {
    .block; 
    border: 1px solid #EEE;
}

会输出:

.block {
    margin: 10px 5px;
    padding: 2px;
}
p {
    margin: 10px 5px;
    padding: 2px; 
    border: 1px solid #EEE;
}

而咱们指望的输出实际是:

.block,
p {
    margin: 10px 5px;
    padding: 2px;
}
p {
    border: 1px solid #EEE;
}

用继承就能够实现上面的输出,不会有重复的代码(以SASS为例):

.block {
    margin: 10px 5px;
    padding: 2px;
}
p {
    @extend .block; 
    border: 1px solid #EEE;
}

Stylus的继承来源于SASS,二者使用方式相同。而LESS则用伪类来实现继承:

.block {
    margin: 10px 5px;
    padding: 2px;
}
p {
    &:extend(.block); 
    border: 1px solid #EEE;
}

Less默认只继承父类自己的样式,若是要同时继承嵌套定义在父类做用域下的样式,得使用关键字all,好比&:extend(.block all)。

函数

三种预处理器都有本身的内置函数,例如颜色处理,类型判断等。LESS中不能自定义函数,SASS和Stylus能够。

SASS自定义函数用法以下,须要使用@function,并用@return指令返回结果:

@function pxToRem($px) {
    @return $px / 2;
}

body{
    font-size: pxToRem(32px);
}

Stylus中则无需这些指令:

pxToRem(n)
    n / 2
body
    font-size: pxToRem(32px)

@import

@import的做用是从其余样式表导入样式,三种预处理器的@import的使用方式各不相同。

除了基本的功能外,LESS引入了import选项来扩展@import的语法。语法以下:

@import (keyword) "filename";

其中keyword能够是以下几种选项(能够联合使用)。
1.reference:使用一个外部文件参与编译,但不输出其内容。
2.inline:直接将引入的文件放入输出文件中,但不处理这个引入的文件。
3.less:无论文件扩展名是什么都将该文件做为一个LESS文件处理。
4.css:无论文件扩展名是什么都将该文件做为一个CSS文件处理。
5.once:只引入文件一次(去重),这是默认方式。
6.multiple:能够引入文件屡次。

SASS则没有LESS的这些扩展语法,它本身推断引入的方式。它的@import 不会被去重,屡次引入会致使一个样式文件被屡次输出到编译结果中。

Stylus的@import和SASS同样都是本身推断引入的方式,可是Stylus能够进行引入文件的去重,它有一个自定义的指令@require,用法和@import同样,但引入的文件只会编译一次。

运算符

三种预处理器都具备运算的特性,能够对数值型的Value(如:数字、颜色、变量等)进行加减乘除四则运算。
Stylus的中文文档中,详细讨论了Stylus的运算符

逻辑控制

Sass中经过@iF 、@else 实现条件判断来提供语言的流控制,经过@for、@each、@while实现循环,而后配合map和list这两种数据类型能够实现多数编程语言提供的功能。
SASS中还实现了一个三目判断,语法为:if($condition, $if_true, $if_false) 。三个参数分别表示:条件,条件为真的值,条件为假的值。

Stylus中经过if、else if、else、unless(基本与if相反)实现条件判断来提供语言的流控制,经过for/in实现循环迭代。

而LESS中没有上述复杂的语法,只经过guarded mixins代替if/else实现简单的条件判断。举例以下:

.mixin (@a) when (lightness(@a) >= 50%) {
    background-color: black;
}
.mixin (@a) when (lightness(@a) < 50%) {
    background-color: white;
}
.mixin (@a) {
    color: @a;
}

以上就是三种CSS预处理器的主要区别,实际项目中使用哪一种CSS预处理器还须要本身斟酌,多踩坑才能体会到哪一种预处理器最适合你当前的项目。

相关文章
相关标签/搜索