在寫CSS的時候咱們會發現,爲了兼容瀏覽器等緣由,咱們每每須要寫不少冗餘的代碼,CSS預處理器就是爲了解決CSS的這些問題,簡化CSS代碼的編寫。php
目前最主流的CSS預處理器是LESS、SASS和Stylus,最近花了幾天時間學習並使用了它們,因而就想對這三個預處理器作個比較。根據這三種語言的特性,主要從一下幾個方面進行討論:css
基本語法web
變量編程
嵌套瀏覽器
混入(mixin)sass
繼承less
函數編程語言
@import函數
運算符學習
邏輯控制
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中,經過選擇器插值生成的規則沒法被繼承。
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; }
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的使用方式各不相同。
除了基本的功能外,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預處理器還須要本身斟酌,多踩坑才能體會到哪一種預處理器最適合你當前的項目。