CSS預處理器——SASS學習筆記(二)

Sass的控制命令

1. @if

@if 指令是一個 SassScript,它可以根據條件來處理樣式塊,如果條件爲 true 返回一個樣式塊,反之 false 返回另一個樣式塊。在 Sass 中除了 @if 外,還可以配合

 @else if 和 @else 一起使用。

假設要控制一個元素隱藏或顯示,我們就可以定義一個混合宏,通過 @if...@else... 來判斷傳進參數的值來控制 display 的值。如下所示:

//SCSS
@mixin blockOrHidden($boolean:true) {
  @if $boolean {
      @debug "$boolean is #{$boolean}";
      display: block;
    }
  @else {
      @debug "$boolean is #{$boolean}";
      display: none;
    }
}

.block {
  @include blockOrHidden;
}

.hidden{
  @include blockOrHidden(false);
}

編譯出來的CSS:

.block {
  display: block;
}

.hidden {
  display: none;
}

2. @for循環(上)

在製作網格系統的時候,大家應該對 .col1~.col12 這樣的印象較深。在 CSS 中你需要一個一個去書寫,但在 Sass 中,可以使用 @for 循環來完成。在 Sass 的 @for

 循環中有兩種方式:

@for $i from <start> through <end>
@for $i from <start> to <end>
  • $i 表示變量
  • start 表示起始值
  • end 表示結束值

這兩個的區別是關鍵字 through 表示包括 end 這個數,而 to 則不包括 end 這個數。

如下代碼,先來個使用 through 關鍵字的例子:

@for $i from 1 through 3 {
  .item-#{$i} { width: 2em * $i; }
}

編譯出來的 CSS:

.item-1 {
  width: 2em;
}

.item-2 {
  width: 4em;
}

.item-3 {
  width: 6em;
}

再來個 to 關鍵字的例子:

@for $i from 1 to 3 {
  .item-#{$i} { width: 2em * $i; }
}

編譯出來的 CSS:

.item-1 {
  width: 2em;
}

.item-2 {
  width: 4em;
}

3. @for循環(下)

上一小節的那個實例幾乎用不着,哈哈,所以其實是沒什麼營養的東西,只是幫助理解了原來 @for 是這麼回事。怎麼的也不能就這麼忽悠大家啊,大家好不容易抽

空看下文章,就這麼點扯淡的東西怎麼對得住呢。下面再來個營養級別的,@for應用在網格系統生成各個格子 class 的代碼:

//SCSS 
$grid-prefix: col-xs- !default;
$grid-width: 60px !default;
$grid-gutter: 20px !default;

%grid {
  float: left;
  margin-left: $grid-gutter / 2;
  margin-right: $grid-gutter / 2;
}
@for $i from 1 through 12 {
  .#{$grid-prefix}#{$i}{
    width: $grid-width * $i + $grid-gutter * ($i - 1);
    @extend %grid;
  }  
}

編譯出來的 CSS:

.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 {
  float: left;
  margin-left: 10px;
  margin-right: 10px;
}

.col-xs-1 {
  width: 60px;
}

.col-xs-2 {
  width: 140px;
}

.col-xs-3 {
  width: 220px;
}

.col-xs-4 {
  width: 300px;
}

.col-xs-5 {
  width: 380px;
}

.col-xs-6 {
  width: 460px;
}

.col-xs-7 {
  width: 540px;
}

.col-xs-8 {
  width: 620px;
}

.col-xs-9 {
  width: 700px;
}

.col-xs-10 {
  width: 780px;
}

.col-xs-11 {
  width: 860px;
}

.col-xs-12 {
  width: 940px;
}

將上面的示例稍做修改,將 @for through 方式換成 @for to::

//SCSS
@for $i from 1 to 13 {
  .#{$grid-prefix}#{$i}{
    width: $grid-width * $i + $grid-gutter * ($i - 1);
    @extend %grid;
  }  
}

其最終編譯出來的 CSS 代碼和上例所編譯出來的一模一樣。

這兩段 Sass 代碼並無太多差別,只是 @for中的 <end> 取值不同。配合 through 的 <end> 值是 12,其遍歷出來的終點值也是 12,和 <end> 值一樣。配合 to 的

 <end> 值是13,其遍歷出來的終點值是 12,就是 <end> 的值減去 1 。

4. @while循環

@while 指令也需要 SassScript 表達式(像其他指令一樣),並且會生成不同的樣式塊,直到表達式值爲 false 時停止循環。這個和 @for 指令很相似,只要 @while

 後面的條件爲 true 就會執行。

這裏有一個 @while 指令的簡單用例:

//SCSS
$types: 4;
$type-width: 20px;

@while $types > 0 {
    .while-#{$types} {
        width: $type-width + $types;
    }
    $types: $types - 1;
}

編譯出來的 CSS

.while-4 {
  width: 24px;
}

.while-3 {
  width: 23px;
}

.while-2 {
  width: 22px;
}

.while-1 {
  width: 21px;
}

5. @each循環

@each 循環就是去遍歷一個列表,然後從列表中取出對應的值。

@each 循環指令的形式:

@each $var in <list>

在下面的例子中你可以看到,$var 就是一個變量名,<list> 是一個 SassScript 表達式,他將返回一個列表值。變量 $var 會在列表中做遍歷,並且遍歷出與 $var 對應

的樣式塊。

這有一個 @each 指令的簡單示例:

$list: adam john wynn mason kuroir;//$list 就是一個列表

@mixin author-images {
    @each $author in $list {
        .photo-#{$author} {
            background: url("/images/avatars/#{$author}.png") no-repeat;
        }
    }
}

.author-bio {
    @include author-images;
}

編譯出 CSS:

.author-bio .photo-adam {
  background: url("/images/avatars/adam.png") no-repeat; }
.author-bio .photo-john {
  background: url("/images/avatars/john.png") no-repeat; }
.author-bio .photo-wynn {
  background: url("/images/avatars/wynn.png") no-repeat; }
.author-bio .photo-mason {
  background: url("/images/avatars/mason.png") no-repeat; }
.author-bio .photo-kuroir {
  background: url("/images/avatars/kuroir.png") no-repeat; }

sass的函數功能——字符串與數字函數

1. sass的函數簡介

在 Sass 中除了可以定義變量,具有 @extend、%placeholder 和 mixins 等特性之外,還自備了一系列的函數功能。其主要包括:

  • 字符串函數
  • 數字函數
  • 列表函數
  • 顏色函數
  • Introspection 函數
  • 三元函數等

當然除了自備的函數功能之外,我們還可以根據自己的需求定義函數功能,常常稱之爲自定義函數。

2. 字符串函數

字符串函數顧名思意是用來處理字符串的函數。Sass 的字符串函數主要包括兩個函數:

  •       unquote($string):刪除字符串中的引號;
  •       quote($string):給字符串添加引號。

1)、unquote()函數

unquote() 函數主要是用來刪除一個字符串中的引號,如果這個字符串沒有帶有引號,將返回原始的字符串。簡單的使用終端來測試這個函數的運行結果:

//SCSS
.test1 {
    content:  unquote('Hello Sass!') ;
}
.test2 {
    content: unquote("'Hello Sass!");
}
.test3 {
    content: unquote("I'm Web Designer");
}
.test4 {
    content: unquote("'Hello Sass!'");
}
.test5 {
    content: unquote('"Hello Sass!"');
}
.test6 {
    content: unquote(Hello Sass);
}

編譯後的 css 代碼:

//CSS
.test1 {
  content: Hello Sass!; }

.test2 {
  content: 'Hello Sass!; }

.test3 {
  content: I'm Web Designer; }

.test4 {
  content: 'Hello Sass!'; }

.test5 {
  content: "Hello Sass!"; }

.test6 {
  content: Hello Sass; }

注意:從測試的效果中可以看出,unquote( ) 函數只能刪除字符串最前和最後的引號(雙引號或單引號),而無法刪除字符串中間的引號。如果字符沒有帶引號,返

回的將是字符串本身。

2). quote()函數

quote() 函數剛好與 unquote() 函數功能相反,主要用來給字符串添加引號。如果字符串,自身帶有引號會統一換成雙引號 ""。如:

//SCSS
.test1 {
    content:  quote('Hello Sass!');
}
.test2 {
    content: quote("Hello Sass!");
}
.test3 {
    content: quote(ImWebDesigner);
}
.test4 {
    content: quote(' ');
}

編譯出來的 css 代碼:

//CSS
.test1 {
  content: "Hello Sass!";
}
.test2 {
  content: "Hello Sass!";
}
.test3 {
  content: "ImWebDesigner";
}
.test4 {
  content: "";
}

使用 quote() 函數只能給字符串增加雙引號,而且字符串中間有單引號或者空格時,需要用單引號或雙引號括起,否則編譯的時候將會報錯。

.test1 {
    content:  quote(Hello Sass);
}

這樣使用,編譯器馬上會報錯:

error style.scss (Line 13: $string: ("Hello""Sass") is not a string for `quote')

解決方案就是去掉空格,或者加上引號:

.test1 {
    content:  quote(HelloSass);
}
.test1 {
    content:  quote("Hello Sass");
}

同時 quote() 碰到特殊符號,比如: !、?、> 等,除中折號 - 和 下劃線_ 都需要使用雙引號括起,否則編譯器在進行編譯的時候同樣會報錯:

error style.scss (Line 13: Invalid CSS after "...quote(HelloSass": expected ")", was "!);")
error style.scss (Line 16: Invalid CSS after "...t:  quote(Hello": expected ")", was “?);")

3). to-upper-case()、to-lower-case()函數

1、To-upper-case()

To-upper-case() 函數將字符串小寫字母轉換成大寫字母。如:

//SCSS
.test {
  text: to-upper-case(aaaaa);
  text: to-upper-case(aA-aAAA-aaa);
}

編譯出來的 css 代碼:

//CSS
.test {
  text: AAAAA;
  text: AA-AAAA-AAA;
}

2、To-lower-case()

To-lower-case() 函數 與 To-upper-case() 剛好相反,將字符串轉換成小寫字母:

//SCSS
.test {
  text: to-lower-case(AAAAA);
  text: to-lower-case(aA-aAAA-aaa);
}

編譯出來的 css 代碼:

//CSS
.test {
  text: aaaaa;
  text: aa-aaaa-aaa;
}

3. 數字函數

Sass 中的數字函數提要針對數字方面提供一系列的函數功能:

  •       percentage($value):將一個不帶單位的數轉換成百分比值;
  •       round($value):將數值四捨五入,轉換成一個最接近的整數;
  •       ceil($value):將大於自己的小數轉換成下一位整數;
  •       floor($value):將一個數去除他的小數部分;
  •       abs($value):返回一個數的絕對值;
  •       min($numbers…):找出幾個數值之間的最小值;
  •       max($numbers…):找出幾個數值之間的最大值;
  •       random(): 獲取隨機數

1). percentage()函數

percentage()函數主要是將一個不帶單位的數字轉換成百分比形式:

>> percentage(.2)
20%
>> percentage(2px / 10px)
20%
>> percentage(2em / 10em)
20%
.footer{
    width : percentage(.2)
}

編譯後的 css 代碼:

.footer{
    width : 20%
}

如果您轉換的值是一個帶有單位的值,那麼在編譯的時候會報錯誤信息:

>> percentage(2px / 10em)
SyntaxError: $value: 0.2px/em is not a unitless number for `percentage'

2). round()函數

round() 函數可以將一個數四捨五入爲一個最接近的整數:

>> round(12.3)
12
>> round(12.5)
13
>> round(1.49999)
1
>> round(2.0)
2
>> round(20%)
20%
>> round(2.2%)
2%
>> round(3.9em)
4em
>> round(2.3px)
2px
>> round(2px / 3px)
1
>> round(1px / 3px)
0
>> round(3px / 2em)
報錯,兩邊單位要相同
.footer {
   width:round(12.3px)
}

編譯後的 css 代碼:

.footer {
  width: 12px;
}

在round() 函數中可以攜帶單位的任何數值。

3). ceil()函數

ceil() 函數將一個數轉換成最接近於自己的整數,會將一個大於自身的任何小數轉換成大於本身 1 的整數。也就是隻做入,不做舍的計算:

>> ceil(2.0)
2
>> ceil(2.1)
3
>> ceil(2.6)
3
>> ceil(2.3%)
3%
>> ceil(2.3px)
3px
>> ceil(2.5px)
3px
>> ceil(2px / 3px)
1
.footer {
   width:ceil(12.3px);
}

編譯後的 css 代碼:

.footer {
  width: 13px;
}

4). floor()函數

floor() 函數剛好與 ceil() 函數功能相反,其主要將一個數去除其小數部分,並且不做任何的進位。也就是隻做舍,不做入的計算:

>> floor(2.1)
2
>> floor(2.5)
2
>> floor(3.5%)
3%
>> floor(10.2px)
10px
>> floor(10.8em)
10em
>> floor(2px / 10px)
0
>> floor(3px / 1em)
報錯,兩邊單位要相同
.footer {
   width:floor(12.3px);
}

編譯後的 css 代碼:

.footer {
  width: 12px;
}

5). abs()函數

abs( ) 函數會返回一個數的絕對值。

>> abs(10)
10
>> abs(-10)
10
>> abs(-10px)
10px
>> abs(-2em)
2em
>> abs(-.5%)
0.5%
>> abs(-1px / 2px)
0.5
.footer {
   width:abs(-12.3px);
}

編譯後的 css 代碼:

.footer {
  width: 12.3px;
}

6). min()、max()函數

1、min()函數

min() 函數功能主要是在多個數之中找到最小的一個,這個函數可以設置任意多個參數:

>> min(1,2,1%,3,300%)
1%
>> min(1px,2,3px)
1px
>> min(1em,2em,6em)
1em

不過在 min() 函數中同時出現兩種不同類型的單位,將會報錯誤信息:

>> min(1px,1em)
SyntaxError: Incompatible units: 'em' and 'px'.

2、max()函數

max() 函數和 min() 函數一樣,不同的是,max() 函數用來獲取一系列數中的最大那個值:

>> max(1,5)
5
>> max(1px,5px)
5px

同樣的,如果在 max() 函數中有不同單位,將會報錯:

>> max(1,3px,5%,6)
SyntaxError: Incompatible units: '%' and ‘px'.

7).random()函數

random() 函數是用來獲取一個隨機數:

>> random()
0.03886
>> random()
0.66527
>> random()
0.8125
>> random()
0.26839
>> random()
0.85063

sass的函數功能——列表函數

1.列表函數簡介

列表函數主要包括一些對列表參數的函數使用,主要包括以下幾種:

  •       length($list):返回一個列表的長度值;
  •       nth($list, $n):返回一個列表中指定的某個標籤值
  •       join($list1, $list2, [$separator]):將兩個列給連接在一起,變成一個列表;
  •       append($list1, $val, [$separator]):將某個值放在列表的最後;
  •       zip($lists…):將幾個列表結合成一個多維的列表;
  •       index($list, $value):返回一個值在列表中的位置值。

2.length()函數

length() 函數主要用來返回一個列表中有幾個值,簡單點說就是返回列表清單中有多少個值:

>> length(10px)
1
>> length(10px 20px (border 1px solid) 2em)
4
>> length(border 1px solid)
3

length() 函數中的列表參數之間使用空格隔開,不能使用逗號,否則函數將會出錯:

>> length(10px,20px,(border 1px solid),2em)
SyntaxError: wrong number of arguments (4 for 1) for `length'
>> length(1,2px)
SyntaxError: wrong number of arguments (2 for 1) for `length'

3.nth()函數

語法:

nth($list,$n)

nth() 函數用來指定列表中某個位置的值。不過在 Sass 中,nth() 函數和其他語言不同,1 是指列表中的第一個標籤值,2 是指列給中的第二個標籤值,依此類推。如:

>> nth(10px 20px 30px,1)
10px
>> nth((Helvetica,Arial,sans-serif),2)
"Arial"
>> nth((1px solid red) border-top green,1)
(1px "solid" #ff0000)

注:在 nth($list,$n) 函數中的 $n 必須是大於 0 的整數:

>> nth((1px solid red) border-top green 1 ,0)
SyntaxError: List index 0 must be a non-zero integer for `nth'

4.join()函數

join() 函數是將兩個列表連接合併成一個列表。

>> join(10px 20px, 30px 40px)
(10px 20px 30px 40px)
>> join((blue,red),(#abc,#def))
(#0000ff, #ff0000, #aabbcc, #ddeeff)
>> join((blue,red),(#abc #def))
(#0000ff, #ff0000, #aabbcc, #ddeeff)

不過 join() 只能將兩個列表連接成一個列表,如果直接連接兩個以上的列表將會報錯:

>> join((blue red),(#abc, #def),(#dee #eff))
SyntaxError: $separator: (#ddeeee #eeffff) is not a string for `join'

但很多時候不只碰到兩個列表連接成一個列表,這個時候就需要將多個 join() 函數合併在一起使用:

>> join((blue red), join((#abc #def),(#dee #eff)))
(#0000ff #ff0000 #aabbcc #ddeeff #ddeeee #eeffff)

在 join() 函數中還有一個很特別的參數 $separator,這個參數主要是用來給列表函數連接列表值是,使用的分隔符號,默認值爲 auto。

join() 函數中 $separator 除了默認值 auto 之外,還有 comma 和 space 兩個值,其中 comma 值指定列表中的列表項值之間使用逗號(,)分隔,space 值指定列表

中的列表項值之間使用空格( )分隔。

在 join() 函數中除非明確指定了 $separator值,否則將會有多種情形發生:

如果列表中的第一個列表中每個值之間使用的是逗號(,),那麼 join() 函數合併的列表中每個列表項之間使用逗號,分隔:

>> join((blue, red, #eff),(green orange))
(#0000ff, #ff0000, #eeffff, #008000, #ffa500)

但當第一個列表中只有一個列表項,那麼 join() 函數合併的列表項目中每個列表項目這間使用的分隔符號會根據第二個列表項中使用的,如果第二列表項中使用是,分

隔,則使用逗號分隔;如果第二列項之間使用的空格符,則使用空格分隔:

>> join(blue,(green, orange))
(#0000ff, #008000, #ffa500)
>> join(blue,(green orange))
(#0000ff #008000 #ffa500)

如果列表中的第一個列表中每個值之間使用的是空格,那麼 join() 函數合併的列表中每個列表項之間使用空格分隔:

>> join((blue green),(red,orange))
(#0000ff #008000 #ff0000 #ffa500)
>> join((blue green),(red orange))
(#0000ff #008000 #ff0000 #ffa500)

如果當兩個列表中的列表項小於1時,將會以空格分隔:

>> join(blue,red)
(#0000ff #ff0000)

如此一來,會有多種情形發生,造成使用混亂的情形,如果你無法記得,什麼時候會是用逗號分隔合併的列表項,什麼時候是使用空格分隔合併 的列表項,在些建議

大家使用 join() 函數合併列表項的時候就明確指定 $separator 參數,用來指定合併的列表中使用什麼方式來分隔列表項:

>> join(blue,red,comma)
(#0000ff, #ff0000)
>> join(blue,red,space)
(#0000ff #ff0000)
>> join((blue green),(red,orange),comma)
(#0000ff, #008000, #ff0000, #ffa500)
>> join((blue green),(red,orange),space)
(#0000ff #008000 #ff0000 #ffa500)
>> join((blue, green),(red,orange),comma)
(#0000ff, #008000, #ff0000, #ffa500)
>> join((blue, green),(red,orange),space)
(#0000ff #008000 #ff0000 #ffa500)
>> join(blue,(red,orange),comma)
(#0000ff, #ff0000, #ffa500)
>> join(blue,(red,orange),space)
(#0000ff #ff0000 #ffa500)
>> join(blue,(red orange),comma)
(#0000ff, #ff0000, #ffa500)
>> join(blue,(red orange),space)
(#0000ff #ff0000 #ffa500)

5. append()函數

append() 函數是用來將某個值插入到列表中,並且處於最末位

>> append(10px 20px ,30px)
(10px 20px 30px)
>> append((10px,20px),30px)
(10px, 20px, 30px)
>> append(green,red)
(#008000 #ff0000)
>> append(red,(green,blue))
(#ff0000 (#008000, #0000ff))

如果沒有明確的指定 $separator 參數值,其默認值是 auto。

  • 如果列表只有一個列表項時,那麼插入進來的值將和原來的值會以空格的方式分隔。
  • 如果列表中列表項是以空格分隔列表項,那麼插入進來的列表項也將以空格分隔;
  • 如果列表中列表項是以逗號分隔列表項,那麼插入進來的列表項也將以逗號分隔。

當然,在 append() 函數中,可以顯示的設置 $separator 參數,

  • 如果取值爲 comma 將會以逗號分隔列表項
  • 如果取值爲 space 將會以空格分隔列表項
>> append((blue green),red,comma)
(#0000ff, #008000, #ff0000)
>> append((blue green),red,space)
(#0000ff #008000 #ff0000)
>> append((blue, green),red,comma)
(#0000ff, #008000, #ff0000)
>> append((blue, green),red,space)
(#0000ff #008000 #ff0000)
>> append(blue,red,comma)
(#0000ff, #ff0000)
>> append(blue,red,space)
(#0000ff #ff0000)

6. zip()函數

zip()函數將多個列表值轉成一個多維的列表:

>> zip(1px 2px 3px,solid dashed dotted,green blue red)
((1px "solid" #008000), (2px "dashed" #0000ff), (3px "dotted" #ff0000))

在使用zip()函數時,每個單一的列表個數值必須是相同的:

>> zip(1px 2px 3px, solid , green blue red)
NoMethodError: undefined method `options=' for nil:NilClass
  Use --trace for backtrace.

否則將會出錯。

zip()函數中每個單一列表的值對應的取其相同位置值:

|--- List ---|--- nth(1) ---|--- nth(2) ---|--- nth(3) ---|
|------------|--------------|--------------|--------------|
|    List1   |      1px     |      2px     |      3px     |
|------------|--------------|--------------|--------------|
|    List2   |      solid   |      dashed  |     dotted   |
|------------|--------------|--------------|--------------|
|    List3   |      green   |      blue    |      red     |
|------------|--------------|--------------|--------------|


zip()函數組合出來就成了:

1px solid green, 2px dashed blue, 3px dotted red

7. index()函數

index() 函數類似於索引一樣,主要讓你找到某個值在列表中所處的位置。在 Sass 中,第一個值就是1,第二個值就是 2,依此類推:

>> index(1px solid red, 1px)
1
>> index(1px solid red, solid)
2
>> index(1px solid red, red)
3

在 index() 函數中,如果指定的值不在列表中(沒有找到相應的值),那麼返回的值將是 false,相反就會返回對應的值在列表中所處的位置。

>> index(1px solid red,dotted) //列表中沒有找到 dotted
false(但編譯結果中不會出現)
>> index(1px solid red,solid) //列表中找到 solid 值,並且返回他的位置值 2
2

8.  introspection()函數

Introspection 函數包括了幾個判斷型函數:

  • type-of($value):返回一個值的類型
  • unit($number):返回一個值的單位
  • unitless($number):判斷一個值是否帶有單位
  • comparable($number-1, $number-2):判斷兩個值是否可以做加、減和合並

這幾個函數主要用來對值做一個判斷的作用,我們來依次看每個函數的功能。

1). type-of()函數

type-of() 函數主要用來判斷一個值是屬於什麼類型:

返回值:

  • number 爲數值型。
  • string 爲字符串型。
  • bool 爲布爾型。
  • color 爲顏色型。
>> type-of(100)
"number"
>> type-of(100px)
"number"
>> type-of("asdf")
"string"
>> type-of(asdf)
"string"
>> type-of(true)
"bool"
>> type-of(false)
"bool"
>> type-of(#fff)
"color"
>> type-of(blue)
"color"
>> type-of(1 / 2 = 1)
"string"

2). unit()函數

unit() 函數主要是用來獲取一個值所使用的單位,碰到複雜的計算時,其能根據運算得到一個“多單位組合”的值,不過只充許乘、除運算:

>> unit(100)
""
>> unit(100px)
"px"
>> unit(20%)
"%"
>> unit(1em)
"em"
>> unit(10px * 3em)
"em*px"
>> unit(10px / 3em)
"px/em"
>> unit(10px * 2em / 3cm / 1rem)
"em/rem"

但加、減碰到不同單位時,unit() 函數將會報錯,除 px 與 cm、mm 運算之外:

>> unit(1px + 1cm)
"px"
>> unit(1px - 1cm)
"px"
>> unit(1px + 1mm)
"px"
>> unit(10px * 2em - 3cm / 1rem)
SyntaxError: Incompatible units: 'cm' and 'px*em'.
>> unit(10px * 2em - 1px / 1rem)
SyntaxError: Incompatible units: '' and 'em'.
>> unit(1px - 1em)
SyntaxError: Incompatible units: 'em' and 'px'.
>> unit(1px - 1rem)
SyntaxError: Incompatible units: 'rem' and 'px'.
>> unit(1px - 1%)
SyntaxError: Incompatible units: '%' and 'px'.
>> unit(1cm + 1em)
SyntaxError: Incompatible units: 'em' and 'cm'.

unit() 函數對於單位運算相對來說也沒有規律,而且有些單位也無法整合成一個單位,對於我們在 CSS 中運用中並不適合,比如:

>> unit(10px * 3em)
"em*px"
>> unit(10px / 3em)
"px/em"
>> unit(10px * 2em / 3cm / 1rem)
"em/rem"

換句話說,上面運算出來的單位,對於在 CSS 中使用將是沒有任何意義的。

3). unitless()函數

unitless() 函數相對來說簡單明瞭些,只是用來判斷一個值是否帶有單位,如果不帶單位返回的值爲 true,帶單位返回的值爲 false:

>> unitless(100)
true
>> unitless(100px)
false
>> unitless(100em)
false
>> unitless(100%)
false
>> unitless(1 /2 )
true
>> unitless(1 /2 + 2 )
true
>> unitless(1px /2 + 2 )
false

具體例子如下,代碼實現:用戶在調用混合宏時,如果用戶沒有給參數值加上單位,程序會自動加入單位

@mixin adjust-location($x, $y) {
  @if unitless($x) {    
    $x: 1px * $x;
  }
  @if unitless($y) {    
    $y: 1px * $y;
  }
  position: relative; 
  left: $x; 
  top: $y;
}
.botton{
    @include adjust-location(20px, 30);
}

編譯後的CSS:

.botton {
  position: relative;
  left: 20px;
  top: 30px; 
}

4). comparable()函數

comparable() 函數主要是用來判斷兩個數是否可以進行“加,減”以及“合併”。如果可以返回的值爲 true,如果不可以返回的值是 false:

>> comparable(2px,1px)
true
>> comparable(2px,1%)
false
>> comparable(2px,1em)
false
>> comparable(2rem,1em)
false
>> comparable(2px,1cm)
true
>> comparable(2px,1mm)
true
>> comparable(2px,1rem)
false
>> comparable(2cm,1mm)
true

9.Miscellaneous()函數

在這裏把 Miscellaneous 函數稱爲三元條件函數,主要因爲他和 JavaScript 中的三元判斷非常的相似。他有兩個值,當條件成立返回一種值,當條件不成立時返回另

一種值:

if($condition,$if-true,$if-false)

上面表達式的意思是當 $condition 條件成立時,返回的值爲 $if-true,否則返回的是 $if-false 值。

>> if(true,1px,2px)
1px
>> if(false,1px,2px)
2px

10. Map

Sass 的 map 常常被稱爲數據地圖,也有人稱其爲數組,因爲他總是以 key:value 成對的出現,但其更像是一個 JSON 數據。

{
"employees": [
{ "firstName":"John" , "lastName":"Doe" },
{ "firstName":"Anna" , "lastName":"Smith" },
{ "firstName":"Peter" , "lastName":"Jones" }
]
}

那麼 Sass 的 map 長得與 JSON 極其相似:

$map: (
    $key1: value1,
    $key2: value2,
    $key3: value3
)

首先有一個類似於 Sass 的變量一樣,用個 $ 加上命名空間來聲明 map。後面緊接是一個小括號 (),將數據以 key:value 的形式賦予,其中 key 和 value 是成對出

現,並且每對之間使用逗號 (,) 分隔,其中最後一組後面沒有逗號。

其中鍵 key 是用來查找相關聯的值 value。使用 map 可以很容易收集鍵的值和動態插入。我們來回憶一下,在 Sass 中常用下面的方式定義變量:

$default-color: #fff !default;
$primary-color: #22ae39 !default;

我們使用 map 可以更好的進行管理:

$color: (
    default: #fff,
    primary: #22ae39
);

如果哪一天,你需要新增加顏色變量值,在 map 中可以非常隨意的添加:

$color: (
    default: #fff,
    primary: #22ae39,
    negative: #d9534f
);

對於 Sass 的 map,還可以讓 map 嵌套 map。其實就是 map 的某一個 key 當成 map,裏面可以繼續放一對或者多對 key:value:

$map: (
    key1: value1,
    key2: (
        key-1: value-1,
        key-2: value-2,
    ),
    key3: value3
);

map 的嵌套實用性也非常的強,大家可能有碰到過換皮膚的項目,可能每一套皮膚對應的顏色蠻多的,那麼使用此功能來管理顏色的變量就非常的有條理性,便於維

護與管理。你可以這樣使用:

$theme-color: (
    default: (
        bgcolor: #fff,
        text-color: #444,
        link-color: #39f
    ),
    primary:(
        bgcolor: #000,
        text-color:#fff,
        link-color: #93f
    ),
    negative: (
        bgcolor: #f36,
        text-color: #fefefe,
        link-color: #d4e
    )
);

在一些介紹 map 的老教程中,你會看到這樣的方式聲明 map:

$map: (
    key1 value1,
    key2 value2,
    key3 value3
);

或者:

$map:(
    key1 value1,
    key2 value2,
    key3 (
        key-1 value-1,
        key-2 value-2
    ),
    key4 value4
);

雖然也能編譯出 CSS,但建議不這樣使用。

11. Sass Maps的函數

前面介紹了使用 map 來管理變量,但要在 Sass 中獲取變量,或者對 map 做更多有意義的操作,我們必須藉助於 map 的函數功能。在 Sass 中 map 自身帶了七個

函數:

  • map-get($map,$key):根據給定的 key 值,返回 map 中相關的值。
  • map-merge($map1,$map2):將兩個 map 合併成一個新的 map。
  • map-remove($map,$key):從 map 中刪除一個 key,返回一個新 map。
  • map-keys($map):返回 map 中所有的 key。
  • map-values($map):返回 map 中所有的 value。
  • map-has-key($map,$key):根據給定的 key 值判斷 map 是否有對應的 value 值,如果有返回 true,否則返回 false。
  • keywords($args):返回一個函數的參數,這個參數可以動態的設置 key 和 value。

1). map-get($map,$key)函數

map-get($map,$key) 函數的作用是根據 $key 參數,返回 $key 在 $map 中對應的 value 值。如果 $key 不存在 $map中,將返回 null 值。此函數包括兩個參數:

  • $map:定義好的 map。
  • $key:需要遍歷的 key。

來看一個簡單的示例,假設定義了一個 $social-colors 的 map:

$social-colors: (
    dribble: #ea4c89,
    facebook: #3b5998,
    github: #171515,
    google: #db4437,
    twitter: #55acee
);

假設要獲取 facebook 鍵值對應的值 #3b5998,我們就可以使用 map-get() 函數來實現:

.btn-dribble{
  color: map-get($social-colors,facebook);
}

編譯出來的CSS:

.btn-dribble {
  color: #3b5998;
}

我們來看另一種情況,假設 $social-colors 這個 map 沒有 $weibo 這個 key:

.btn-weibo{
  font-size: 12px;
  color: map-get($social-colors,weibo);
}

此時編譯出來的是CSS:

.btn-weibo {
  font-size: 12px;
}

從 編譯出來的 CSS 可以得知,如果 $key 不在 $map 中,不會編譯出 CSS,其實在 Sass 中,map-get($social- colors,weibo) 返回了一個 null 值。但在編譯出來的

 CSS 中,你只知道他沒有編譯出樣式,而且在命令終端編譯時,也沒有任何錯誤或者警告信息。說實話,你並不知道他爲什麼編譯不出來樣式,或者說他已返回了

值爲 null。體驗不強,也不好排錯。其實如果我們自定義一個函數,另外加個判斷,那就截然不同。

2). map-has-key($map,$key)函數

map-has-key($map,$key) 函數將返回一個布爾值。當 $map 中有這個 $key,則函數返回 true,否則返回 false。

前面的示例,當 $key 不在 $map 中時,使用 map-get($map,$key) 函數將返回一個 null 值。但對於開發人員,並看不到任何提示信息。如果使用 map-has-

key($map,$key) 函數就可以改變這一狀態。我們來看一個簡單的示例。

@if map-has-key($social-colors,facebook){
    .btn-facebook {
        color: map-get($social-colors,facebook);
    }
} @else {
    @warn "No color found for faceboo in $social-colors map. Property ommitted."
}

編譯出來:

.btn-fackbook{
    color: #3b5998;
}   

上面看到的示例是 facebook 這個 key 已存在 $social-colors 這個 map 當中。所以能正常編譯。如果你手誤,將 facebook 輸錯了:

@if map-has-key($social-colors,faceboo){
    .btn-facebook {
        color: map-get($social-colors,facebook);
    }
} @else {
    @warn "No color found for faceboo in $social-colors map. Property ommitted."
}

這個時候,你編譯出來的 CSS 代碼中,不會有新代碼添加,但在命令終端可以看到提示信息:

WARNING: No color found for faceboo in $social-colors map. Property ommitted.
         on line 25 of test.scss

是不是非常的友好。但總覺得這樣寫是傻傻的,總不可能每獲取一個 key 都寫一個 @if 語句吧。其實不用這麼複雜,我們可以自定義一個函數,比如 colors():

@function colors($color){
    @if not map-has-key($social-colors,$color){
        @warn "No color found for `#{$color}` in $social-colors map. Property omitted.";
    }
    @return map-get($social-colors,$color);
}

有了這個函數之後,我們就可以這樣使用

.btn-dribble {
    color: colors(dribble);
}
.btn-facebook {
    color: colors(facebook);
}
.btn-github {
    color: colors(github);
}
.btn-google {
    color: colors(google);
}
.btn-twitter {
    color: colors(twitter);
}
.btn-weibo {
    color: colors(weibo);
}

編譯出來的 CSS:

.btn-dribble {
  color: #ea4c89;
}

.btn-facebook {
  color: #3b5998;
}

.btn-github {
  color: #171515;
}

.btn-google {
  color: #db4437;
}

.btn-twitter {
  color: #55acee;
}

同時你不難發現,命令終端提示信息:

WARNING: No color found for `weibo` in $social-colors map. Property omitted.
         on line 13 of test.scss

那是在 $social-colors 這個 map 中沒有 weibo 這個 key。是不是很有意思。

當然,如果你對 Sass 的指令熟悉的話,上面編譯出來的 CSS 可以使用 @each:

@each $social-network,$social-color in $social-colors {
    .btn-#{$social-network} {
        color: colors($social-network);
    }
}

3). map-keys($map)函數

map-keys($map) 函數將會返回 $map 中的所有 key。這些值賦予給一個變量,那他就是一個列表。如:

map-keys($social-colors);

其返回的值爲:

"dribble","facebook","github","google","twitter"

換句話說:

$list: map-keys($social-colors);

相當於:

$list:"dribble","facebook","github","google","twitter";

這個時候,就可以配合 Sass 的 list 做很多事情。

上面的示例,可以做通過 map-keys($map) 來做一個修改:

@function colors($color){
    $names: map-keys($social-colors);
    @if not index($names,$color){
        @warn "Waring: `#{$color} is not a valid color name.`";
    }
    @return map-get($social-colors,$color);
}

上面代碼中最不同之處,我們使 用map-key s將 $social-colors 這個 map 的所有 key 取出,並賦予給一個名 爲 $names 的列表。然後通過 index($names,$color) 返

回 $color 在 $names 位置,如果這個位置不存在,將返回提示信息,如果存在將返回正確的值。

.btn-weibo{
    color: colors(weibo);
}

例如,weibo 不在 $social-color s中,那麼不會編譯出 CSS,而且在命令終端同樣會有提示信息:

WARNING: Waring: `weibo is not a valid color name.`
         on line 27 of test.scss

同樣,也可以通過 @each 或者 @for 遍歷出所有值:

@each:

@each $name in map-keys($social-colors){
    .btn-#{$name}{
        color: colors($name);
    }
}

@for:

@for $i from 1 through length(map-keys($social-colors)){
    .btn-#{nth(map-keys($social-colors),$i)} {
        color: colors(nth(map-keys($social-colors),$i));
    }
}

雖然使用的方法不一樣,但最終得到的 CSS 是一樣的:

.btn-dribble {
  color: #ea4c89;
}

.btn-facebook {
  color: #3b5998;
}

.btn-github {
  color: #171515;
}

.btn-google {
  color: #db4437;
}

.btn-twitter {
  color: #55acee;
}

4). map-values($map)函數

map-values($map) 函數類似於 map-keys($map) 功能,不同的是 map-values($map )獲取的是 $map 的所有 value 值,可以說也將是一個列表。而且,map-

values($map) 中如果有相同的 value 也將會全部獲取出來。

如前面的示例,使用:

map-values($social-colors)

將會返回:

#ea4c89,#3b5998,#171515,#db4437,#55acee

值與值之前同樣用逗號分隔。

5). map-merge($map1,$map2)函數

map-merge($map1,$map2) 函數是將 $map1 和 $map2 合併,然後得到一個新的 $map。如果你要快速將新的值插入到 $map 中的話,這種方法是最佳方法。假設

我們有兩個 $map:

$color: (
    text: #f36,
    link: #f63,
    border: #ddd,
    backround: #fff
);
$typo:(
    font-size: 12px,
    line-height: 1.6
);

如果希望將這兩個 $map 合併成一個 map,我們只要這樣做:

$newmap: map-merge($color,$typo);

將會生成一個新的 map:

$newmap:(
    text: #f36,
    link: #f63,
    border: #ddd,
    background: #fff,
    font-size: 12px,
    line-height: 1.6
);

這樣你就可以藉助 map-get( ) 等函數做其他事情了。

不過有一點需要注意,如果 $map1 和 $map2 中有相同的 $key 名,那麼將 $map2 中的 $key 會取代 $map1 中的:

$color: (
    text: #f36,
    link: #f63,
    border: #ddd,
    backround: #fff
);
$typo:(
    font-size: 12px,
    line-height: 1.6,
    border: #ccc,
    background: #000
);

執行:

$newmap: map-merge($color,$typo);

得到的新 map:

$newmap:(
    text: #f36,
    link: #f63,
    font-size: 12px,
    line-height: 1.6,
    border: #ccc,
    background: #000
);

6). map-remove($map,$key)函數

map-remove($map,$key) 函數是用來刪除當前 $map 中的某一個 $key,從而得到一個新的 map。其返回的值還是一個 map。他並不能直接從一個 map 中刪除另一

個 map,僅能通過刪除 map 中的某個 key 得到新 map。如:

$map:map-remove($social-colors,dribble);

返回的是一個新 map:

$map:(
    facebook: #3b5998,
    github: #171515,
    google: #db4437,
    twitter: #55acee
);

如果刪除的 key 並不存在於 $map 中,那麼 map-remove() 函數返回的新 map 和以前的 map 一樣。

$map:map-remove($social-colors,weibo);

返回的值:

$map: (
    dribble: #ea4c89,
    facebook: #3b5998,
    github: #171515,
    google: #db4437,
    twitter: #55acee
);

7). keywords($args)函數

keywords($args) 函數可以說是一個動態創建 map 的函數。可以通過混合宏或函數的參數創建 map。參數也是成對出現,其中 $args 變成 key(會自動去掉$符

號),而 $args 對應的值就是value。

@mixin map($args...){
    @debug keywords($args);
}

@include map(
  $dribble: #ea4c89,
  $facebook: #3b5998,
  $github: #171515,
  $google: #db4437,
  $twitter: #55acee
);

在命令終端可以看到一個輸入的 @debug 信息:

 DEBUG: (dribble: #ea4c89, facebook: #3b5998, github: #171515, google: #db4437, twitter: #55acee)

Sass的函數功能——顏色函數

1. RGB顏色函數

RGB 顏色只是顏色中的一種表達式,其中 R 是 red 表示紅色,G 是 green 表示綠色而 B 是 blue 表示藍色。在 Sass 中爲 RGB 顏色提供六種函數:

  • rgb($red,$green,$blue):根據紅、綠、藍三個值創建一個顏色;
  • rgba($red,$green,$blue,$alpha):根據紅、綠、藍和透明度值創建一個顏色;
  • red($color):從一個顏色中獲取其中紅色值;
  • green($color):從一個顏色中獲取其中綠色值;
  • blue($color):從一個顏色中獲取其中藍色值;
  • mix($color-1,$color-2,[$weight]):把兩種顏色混合在一起。

僅從概念上,或許大家沒有太多的概念,我們通過下面的命令來做一個簡單的測試:

sass -i

在命令終端開啓這個命令,相當於開啓 Sass 的函數計算。

接下來,分別在終端使用 RGB 函數來進行計算,看其最終結果:

$ sass -i
>> rgb(200,40,88) //根據r:200,g:40,b:88計算出一個十六進制顏色值
#c82858
>> rgba(#c82858,.65) //根據#c82858的65%透明度計算出一個rgba顏色值
rgba(200, 40, 88, 0.65)
>> red(#c82858) //從#c82858顏色值中得到紅色值 200
200
>> green(#c82858) //從#c82858顏色值中得到綠色值 40
40
>> blue(#c82858) //從#c82858顏色值中得到藍色值 88
88
>> mix(#c82858,rgba(200,40,80,.65),.3) //把#c82858和rgba(200,40,88,.65) 兩顏色按比例混合得到一個新顏色
rgba(200, 40, 80, 0.65105)

從上面的簡單運算結果可以很清晰的知道。在 RGB 顏色函數中,在實際中常用的主要是 rgba() 和 mix() 兩個函數,而 rgb() 函數只能快速的將一個 rgb 顏色轉換成

十六進制顏色表達,red()、green() 和 blue() 函數,只能取得某一顏色的一個值,對於顏色上使用並無太大作用(或許他的好處,我還沒有理解過來)。接下來,主

要來實戰一下 rgba() 和 mix() 函數在實際中的運用。

1). rgba()函數

rgba() 函數主要用來將一個顏色根據透明度轉換成 rgba 顏色。

其語法有兩種格式:

rgba($red,$green,$blue,$alpha)  //將一個rgba顏色轉譯出來,和未轉譯的值一樣
rgba($color,$alpha)  //將一個Hex顏色轉換成rgba顏色

其中 rgba($color,$alpha) 函數作用更大,主要運用在這樣的情形之中:假設在實際中知道的顏色值是 #f36 或者 red,但在使用中,需要給他們配上一個透明度,這

個時候在原來的 CSS 中,首先需要通過製圖工具,得到 #f36 或 red 顏色的 R、G、B 值,而不能直接使用(注意 css3 是可以的,但是存在瀏覽器兼容問題):

//CSS
color: rgba(#f36,.5); //在css中,這是無效的寫法

但在 Sass 中,RGBA() 函數就能解決這個問題。我們先來看一個簡單的例子,假設在變量中定義了一個基本的變量:

$color: #f36;
$bgColor: orange;
$borderColor:green;

同時給他們加上 .5 的透明度:

//SCSS
.rgba {
    color: rgba(#f36,.5);
    background: rgba(orange,.5);
    border-color: rgba(green,.5);
}

語法:

在這個實例中,我們使用了 Sass 的 rgba 函數,在括號是函數的參數,第一個參數是需要轉換的顏色,他可以是任何顏色的表達方式,也可以是一個顏色變量;第二

個參數是顏色的透明度,其值是 0~1 之間。上面的代碼轉譯出來:

.rgba {
  color: rgba(255, 51, 102, 0.5);
  background: rgba(255, 165, 0, 0.5);
  border-color: rgba(0, 128, 0, 0.5);
}

在來看一個調用前面定義的變量:

//SCSS
.rgba {
    color: rgba($color,.5);
    background: rgba($bgColor,.5);
    border-color: rgba($borderColor,.5);
}

編譯出來的 css 代碼:

//CSS
.rgba {
  color: rgba(255, 51, 102, 0.5);
  background: rgba(255, 165, 0, 0.5);
  border-color: rgba(0, 128, 0, 0.5);
}

我想您應該會看到一個變化,通過 rgba 函數,指定一個透明值,將原色轉換成另外一個顏色:

2). red()函數

red() 函數非常簡單,其主要用來獲取一個顏色當中的紅色值。假設有一個 #f36 的顏色,如果你想得到 #f36 中的 red 值是多少,這個時候使用 red() 函數就能很簡單

獲取。

>> red(#f36)
255

得到的值是”255”。(注意:在命令終端要先輸入sass -i 命令)

3). green()函數

green() 函數和 red() 函數一樣,用來獲取某一個顏色值中 green 的值。同樣拿 ”#f36“ 顏色爲例:

>> green(#f36)
51

4). blue()函數

同理,blue() 函數是用來獲取某一個顏色值中 blue 的值,如:

>> blue(#f36)
102

5). mix()函數

Mix 函數是將兩種顏色根據一定的比例混合在一起,生成另一種顏色。其使用語法如下:

mix($color-1,$color-2,$weight);

$color-1 $color-2 指的是你需要合併的顏色,顏色可以是任何表達式,也可以是顏色變量。

$weight 爲 合併的比例(選擇權重),默認值爲 50%,其取值範圍是 0~1 之間。它是每個 RGB 的百分比來衡量,當然透明度也會有一定的權重。默認的比例是

 50%,這意味着兩個顏色各佔一半,如果指定的比例是 25%,這意味着第一個顏色所佔比例爲 25%,第二個顏色所佔比例爲75%。

其使用方法也很簡單:

mix(#f00, #00f) => #7f007f
mix(#f00, #00f, 25%) => #3f00bf
mix(rgba(255, 0, 0, 0.5), #00f) => rgba(63, 0, 191, 0.75)

在前面的基礎上,做一個修改:

//SCSS
$color1: #a63;
$color2: #fff;
$bgColor1: #f36;
$bgColor2: #e36;
$borderColor1:#c36;
$borderColor2:#b36;

.mix {
    background: mix($bgColor1,$bgColor2,.75);
    color: mix($color1,$color2,.25);
    border-color: mix($borderColor1,$bgColor2,.05);
}

編譯的 css 代碼:

//CSS
.mix {
    background: #ee3366;
    color: #fefefe;
    border-color: #ed33
}

看下對比效果:

這就是 Mix 函數的工作原理,在函數中指定三個函數,前兩個函數是你想混合的顏色(記住,你可以通過顏色變量、十六進制、RGBA、RGB、HSL 或者 HSLA 顏色

值)。第三個參數是第一種顏色的比例值。

2.  HSL顏色函數

在 Sass 中提供了一系列有關於 HSL 的顏色函數,以供大家使用,其中常用的有 saturation、lightness、adjust-hue、lighten、darken 等等。接下來我們先來了解一

下 HSL 顏色函數包括哪些具體的函數,所起的作用是什麼:

  • hsl($hue,$saturation,$lightness):通過色相(hue)、飽和度(saturation)和亮度(lightness)的值創建一個顏色;
  • hsla($hue,$saturation,$lightness,$alpha):通過色相(hue)、飽和度(saturation)、亮度(lightness)和透明(alpha)的值創建一個顏色;
  • hue($color):從一個顏色中獲取色相(hue)值;
  • saturation($color):從一個顏色中獲取飽和度(saturation)值;
  • lightness($color):從一個顏色中獲取亮度(lightness)值;
  • adjust-hue($color,$degrees):通過改變一個顏色的色相值,創建一個新的顏色;
  • lighten($color,$amount):通過改變顏色的亮度值,讓顏色變亮,創建一個新的顏色;
  • darken($color,$amount):通過改變顏色的亮度值,讓顏色變暗,創建一個新的顏色;
  • saturate($color,$amount):通過改變顏色的飽和度值,讓顏色更飽和,從而創建一個新的顏色
  • desaturate($color,$amount):通過改變顏色的飽和度值,讓顏色更少的飽和,從而創建出一個新的顏色;
  • grayscale($color):將一個顏色變成灰色,相當於desaturate($color,100%);
  • complement($color):返回一個補充色,相當於adjust-hue($color,180deg);
  • invert($color):反回一個反相色,紅、綠、藍色值倒過來,而透明度不變。

同樣在你的終端,通過 sass -i 來對上面的各個函數做一個簡單測試:

>> hsl(200,30%,60%) //通過h200,s30%,l60%創建一個顏色
#7aa3b8
>> hsla(200,30%,60%,.8)//通過h200,s30%,l60%,a80%創建一個顏色
rgba(122, 163, 184, 0.8)
>> hue(#7ab)//得到#7ab顏色的色相值
195deg
>> saturation(#7ab)//得到#7ab顏色的飽和度值
33.33333%
>> lightness(#7ab)//得到#7ab顏色的亮度值
60%
>> adjust-hue(#f36,150deg) //改變#f36顏色的色相值爲150deg
#33ff66
>> lighten(#f36,50%) //把#f36顏色亮度提高50%
#ffffff
>> darken(#f36,50%) //把#f36顏色亮度降低50%
#33000d
>> saturate(#f36,50%) //把#f36顏色飽和度提高50%
#ff3366
>> desaturate(#f36,50%) //把#f36顏色飽和度降低50%
#cc667f
>> grayscale(#f36) //把#f36顏色變成灰色
#999999
>> complement(#f36)
#33ffcc
>> invert(#f36)
#00cc99

在 HSL 函數中,hsl() 和 hsla() 函數主要是通過顏色的 H、S、L 或者 A 幾個參數獲取一個 rgb 或 rgba 表達的顏色,這兩個函數與 CSS 中的無太大區別,只是使用

這兩個函數能幫助您知道顏色的十六進制表達式和 rgba 表達式。

而 hue()、saturation() 和 lightness() 函數主要是用來獲取指定顏色中的色相值、飽和度和亮度值。對於顏色表達沒有太多的實際作用。

HSL 函數中最常見的應該是 lighten()、darken()、saturate()、desaturate()、grayscale()、complement()和 invert() 幾個函數。

1). lighten()和darken()函數

lighten() 和 darken() 兩個函數都是圍繞顏色的亮度值做調整的,其中 lighten() 函數會讓顏色變得更亮,與之相反的 darken() 函數會讓顏色變得更暗。這個亮度值可

以是 0~1 之間,不過常用的一般都在 3%~20% 之間。

來看一個簡單的實例,首先定義一個顏色變量:

$baseColor: #ad141e;

使用 lighten() 和 darken() 函數來修改 10% 的亮度值:

//SCSS
.lighten {
    background: lighten($baseColor,10%);
}
.darken{
    background: darken($baseColor,10%);
}

編譯出來的 css 代碼:

//CSS
.lighten {
  background: #db1926;
}

.darken {
  background: #7f0f16;
}


從效果中,明顯看出顏色之間的差異,我們使用函數 lightness() 函數來驗證一下三個顏色之間亮度值的變化:

>> lightness(#ad141e) //原色的亮度值
37.84314%
>> lightness(#db1926) //在原色的亮度值基礎上增加10%
47.84314%
>> lightness(#7f0f16) //在原色的亮度值基礎上減少10%
27.84314%

lighten() 和 darken() 函數只是在原始顏色的基礎上對亮度值進行運算操作,但是生成出來的新顏色在色相和飽和度會有略微的變化,比如上面的實例生成的新顏色與

原始色在色相與飽和度值的對比:

>> hue(#ad141e)
356.07843deg
>> hue(#db1926)
355.97938deg
>> hue(#7f0f16)
356.25deg
>> saturation(#ad141e)
79.27461%
>> saturation(#db1926)
79.5082%
>> saturation(#7f0f16)
78.87324%

如果有點顏色概念基礎的同學應該都清楚,不管什麼顏色當其亮度值 趨近於0時,顏色會越來越暗,直到變成了黑色;反之,當其亮度值趨近於 100% 時,顏色會越

來越亮,直到變成了白色。但當使用 lighten() 和 darken() 函數對一個顏色的亮度值計算時,會碰到兩個極端,lighten() 函數會讓新顏色的亮度值超過 100%,而

 darken() 函數會讓新顏色的亮度值低於 0 變成負數。可實際上任何顏色的亮度值都在 0~100% 之間,如此一來,Sass 的 lighten() 和 darken() 函數又將會如何處理

呢?

帶着上面的疑問,我們一起來做一個簡單性的測試。從上面的示例中得知 #ad1414 的亮度值爲 37.84314%,爲了讓新顏色的亮度值大於 100% 和小於 0,在對應的

函數,做一些調整:

//SCSS
$baseColor:#ad141e;
.lighten {
    background: lighten($baseColor,70%);
}
.darken{
    background: darken($baseColor,40%);
}

編譯出來的 css 代碼:

//CSS
.lighten {
  background: white;
}

.darken {
  background: black;
}

上面的例子說明了一切問題。當顏色的亮度值接近或大於 100%,顏色會變成白色;反之顏色的亮度值接近或小於 0 時,顏色會變成黑色。

2). saturate()和desaturate()函數

saturate()、desaturate()這兩個函數是通過改變顏色的飽和度來得到一個新的顏色,他們和前面介紹的修改亮度得到新顏色的方法非常相似。

//SCSS
$baseColor: #ad141e;
.saturate {
  background: saturate($baseColor,30%); //在原色飽和度基礎上增加飽和度
}
.desaturate {
  background: desaturate($baseColor,30%);//在原色飽和度基礎上減少飽和度
}

編譯出來的 css 代碼:

//CSS
.saturate {
  background: #c1000d;
}

.desaturate {
  background: #903137;
}

顏色變了。同樣使用 saturation() 函數在終端中進行計算一下,看看他們有什麼樣的變化:

>> saturation(#ad141e) //原色的飽和度
79.27461%
>> saturation(#c1000d)  //在原色飽和度基礎上增加30%,超過100%時按100%計算
100%
>> saturation(#903137) //在原色飽和度基礎上減少30%,小於0時按0計算
49.2228%

3). ajust-hue()函數

這個是通過調整顏色的色相換算一個新顏色。他需要一個顏色和色相度數值。通常這個度數值是在 -360deg 至 360deg 之間,當然了可以是百分數:

//SCSS
$baseColor: #ad141e;
.adjust-hue-deg {
  background: adjust-hue($baseColor,30deg);
}
.adjust-hue-per {
  background: adjust-hue($baseColor,30%);
}

編譯出的 css 代碼:

//CSS
.adjust-hue-deg {
  background: #ad5614;
}

.adjust-hue-per {
  background: #ad5614;
}

從轉譯出來的代碼,不難發現他們的顏色是一樣的。嘗試多次,如果兩個值(拋棄 deg 和 100%)相同,計算出來的顏色也會一樣。

同樣的,可以通過 hue() 函數得到顏色轉換前後的色相值:

>> hue(#ad141e) //原顏色色相值
356.07843deg
>> hue(#ad5614) //在原色色相基礎上增加30deg
25.88235deg

這裏有一個很有意思的地方,在 HSL 顏色表達方式上,色相是從 -360 和 360 之間,負值逆時針轉,正值順時針轉。在這個實例中,原色的色相值約 356deg,加上

 30deg 後,新顏色變成了 386deg,但我們的色盤中並沒有比 360deg 更大的值,此時新顏色的值也並不會是386deg,那將怎麼辦呢?其實很簡單,當值大於

 360deg時,表示色盤轉完了一圈,繼續順時針轉餘下的值(這裏是 26deg),那麼這個繼續轉的值就是新顏色的色相值。小夥伴們,看到這個,你是不是又有點驚

了。反之,得到的負數值也是一樣的道理。

4). grayscale()函數

這個函數會顏色的飽和度值直接調至 0%,所以此函數與 desaturate($color,100%) 所起的功能是一樣的。一般這個函數能將彩色顏色轉換成不同程度的灰色。例如:

//SCSS
$baseColor: #ad141e;
.grayscale {
  background: grayscale($baseColor);
}
.desaturate {
  background: desaturate($baseColor,100%);
}

編譯出來的 css 代碼:

//CSS
.grayscale {
  background: #616161;
}

.desaturate {
  background: #616161;
}

看看計算出來的 HSL 各個值的變化:

>> hue(#ad141e)
356.07843deg
>> hue(#616161)
0deg
>> saturation(#ad141e)
79.27461%
>> saturation(#616161)
0%
>> lightness(#ad141e)
37.84314%
>> lightness(#616161)
38.03922%

grayscale() 函數處理過的顏色,其最大的特徵就是顏色的飽和度爲 0。

3. opacity函數

在 CSS 中除了可以使用 rgba、hsla 和 transform 來控制顏色透明度之外,還可以使用 opacity 來控制,只不過前兩者只是針對顏色上的透明通道做處理,而後者是

控制整個元素的透明度。

在 Sass 中,也提供了系列透明函數,只不過這系列的透明函數主要用來處理顏色透明度:

  •       alpha($color) /opacity($color):獲取顏色透明度值;
  •       rgba($color, $alpha):改變顏色的透明度值;
  •       opacify($color, $amount) / fade-in($color, $amount):使顏色更不透明;
  •       transparentize($color, $amount) / fade-out($color, $amount):使顏色更加透明。

1).  alpha()和opacity()函數

alphpa() 和 opacity() 函數很簡單,與前面介紹的 red(),green() 等函數很類似。這個函數的主要功能是用來獲取一個顏色的透明度值。如果顏色沒有特別指定透明

度,那麼這兩個函數得到的值都會是 1:

>> alpha(red)
1
>> alpha(rgba(red,.8))
0.8
>> opacity(red)
1
>> opacity(rgba(red,.8))
0.8

2).  rgba()函數

在前面介紹 RGB 函數一節中,還記得嗎?有一個 rgba() 函數可以創建一個顏色,同時還可以對顏色修改其透明度。其可以接受兩個參數,第一個參數爲顏色,第二

個參數是你需要設置的顏色透明值。

>> rgba(red,.5)
rgba(255, 0, 0, 0.5)
>> rgba(#dedede,.5)
rgba(222, 222, 222, 0.5)
>> rgba(rgb(34,45,44),.5)
rgba(34, 45, 44, 0.5)
>> rgba(rgba(33,45,123,.2),.5)
rgba(33, 45, 123, 0.5)
>> rgba(hsl(33,7%,21%),.5)
rgba(57, 54, 50, 0.5)
>> rgba(hsla(33,7%,21%,.9),.5)
rgba(57, 54, 50, 0.5)

3). opacify()和fade-in函數

這兩個函數是用來對已有顏色的透明度做一個加法運算,會讓顏色更加不透明。其接受兩個參數,第一個參數是原始顏色,第二個參數是你需要增加的透明度值,其

取值範圍主要是在 0~1 之間。當透明度值增加到大於 1 時,會以 1 計算,表示顏色不具有任何透明度。

>> opacify(rgba(22,34,235,.6),.2)
rgba(22, 34, 235, 0.8)
>> opacify(rgba(22,34,235,.6),.5)
#1622eb
>> opacify(hsla(22,34%,23%,.6),.15)
rgba(79, 53, 39, 0.75)
>> opacify(hsla(22,34%,23%,.6),.415)
#4f3527
>> opacify(red,.15)
#ff0000
>> opacify(#89adde,.15)
#89adde
>> fade-in(rgba(23,34,34,.5),.15)
rgba(23, 34, 34, 0.65)
>> fade-in(rgba(23,34,34,.5),.615)
#172222

其中 fade-in( ) 函數又名 fade_in() 函數。其所起作用等效。

4). transparentize()和fade-out()函數

transparentize() 和 fade-out() 函數所起作用剛好與 opacify() 和 fade-in() 函數相反,讓顏色更加的透明。這兩個函數會讓透明值做減法運算,當計算出來的結果小於

 0 時會以 0 計算,表示全透明。

>> transparentize(red,.5)
rgba(255, 0, 0, 0.5)
>> transparentize(#fde,.9)
rgba(255, 221, 238, 0.1)
>> transparentize(rgba(98,233,124,.3),.11)
rgba(98, 233, 124, 0.19)
>> transparentize(rgba(98,233,124,.3),.51)
rgba(98, 233, 124, 0)
>> fade-out(red,.9)
rgba(255, 0, 0, 0.1)
>> fade-out(hsla(98,6%,23%,.5),.1)
rgba(58, 62, 55, 0.4)
>> fade-out(hsla(98,6%,23%,.5),.6)
rgba(58, 62, 55, 0)

Sass的@規則

Sass 支持所有 CSS3 的 @ 規則, 以及一些 Sass 專屬的規則,也被稱爲“指令(directives)”。 這些規則在 Sass 中具有不同的功效,詳細解釋如下。

1. @import

Sass 擴展了 CSS 的 @import 規則,讓它能夠引入 SCSS 和 Sass 文件。 所有引入的 SCSS 和 Sass 文件都會被合併並輸出一個單一的 CSS 文件。 另外,被導入

的文件中所定義的變量或 mixins 都可以在主文件中使用。

Sass 會在當前目錄下尋找其他 Sass 文件, 如果是 Rack、Rails 或 Merb 環境中則是 Sass 文件目錄。 也可以通過 :load_paths 選項或者在命令行中使用 --load-

path 選項來指定額外的搜索目錄。

@import 根據文件名引入。 默認情況下,它會尋找 Sass 文件並直接引入, 但是,在少數幾種情況下,它會被編譯成 CSS 的 @import 規則:

  • 如果文件的擴展名是 .css。
  • 如果文件名以 http:// 開頭。
  • 如果文件名是 url()。
  • 如果 @import 包含了任何媒體查詢(media queries)。

如果上述情況都沒有出現,並且擴展名是 .scss 或 .sass, 該名稱的 Sass 或 SCSS 文件就會被引入。 如果沒有擴展名, Sass 將試着找出具有 .scss 或 .sass 擴展

名的同名文件並將其引入。

例如:

@import "foo.scss";

@import "foo";

兩者都將引入 foo.scss 文件, 而

@import "foo.css";
@import "foo" screen;
@import "http://foo.com/bar";
@import url(foo);

將被編譯爲:

@import "foo.css";
@import "foo" screen;
@import "http://foo.com/bar";
@import url(foo);

也可以通過一個 @import 引入多個文件。例如:

@import "rounded-corners", "text-shadow";

將引入 rounded-corners 和 text-shadow 兩個文件。

如果你有一個 SCSS 或 Sass 文件需要引入, 但是你又不希望它被編譯爲一個 CSS 文件, 這時,你就可以在文件名前面加一個下劃線,就能避免被編譯。 這將告訴

 Sass 不要把它編譯成 CSS 文件。 然後,你就可以像往常一樣引入這個文件了,而且還可以省略掉文件名前面的下劃線。

例如,你有一個文件叫做 _colors.scss。 這樣就不會生成 _colors.css 文件了, 而且你還可以這樣做:

@import "colors";//不用加下劃線

來引入 _colors.scss 文件。

注意,在同一個目錄不能同時存在帶下劃線和不帶下劃線的同名文件。 例如, _colors.scss 不能與 colors.scss 並存。

嵌套 @import

雖然大部分時間只需在頂層文件使用 @import 就行了, 但是,你還可以把他們包含在 CSS 規則 和 @media 規則中。

來看官網提供的一個簡單示例:

假設要引入的樣式文件`example.scss`文件中包含這樣的代碼:

.example {
  color: red;
}

然後這樣引用:

#main {
  @import "example";
}

編譯出來的 CSS:

#main .example {
  color: red;
}

2. @media

Sass 中的 @media 指令和 CSS 的使用規則一樣的簡單,但它有另外一個功能,可以嵌套在 CSS 規則中。有點類似 JS 的冒泡功能一樣,如果在樣式中使用

 @media 指令,它將冒泡到外面。來看一個簡單示例:

.sidebar {
  width: 300px;
  @media screen and (orientation: landscape) {
    width: 500px;
  }
}

編譯出來:

.sidebar {
  width: 300px; }
  @media screen and (orientation: landscape) {
    .sidebar {
      width: 500px; } }

@media 也可以嵌套 @media:

@media screen {
  .sidebar {
    @media (orientation: landscape) {
      width: 500px;
    }
  }
}

此時編譯出來:

@media screen and (orientation: landscape) {
  .sidebar {
    width: 500px; } }

在使用 @media 時,還可以使用插件#{}:

$media: screen;
$feature: -webkit-min-device-pixel-ratio;
$value: 1.5;

@media #{$media} and ($feature: $value) {
  .sidebar {
    width: 500px;
  }
}

編譯出來的 CSS:

@media screen and (-webkit-min-device-pixel-ratio: 1.5) {
  .sidebar {
    width: 500px; } }

3. @extend

Sass 中的 @extend 是用來擴展選擇器或佔位符。比如:

.error {
  border: 1px #f00;
  background-color: #fdd;
}
.error.intrusion {
  background-image: url("/image/hacked.png");
}
.seriousError {
  @extend .error;
  border-width: 3px;
}

被編譯爲:

.error, .seriousError {
  border: 1px #f00;
  background-color: #fdd; }

.error.intrusion, .seriousError.intrusion {
  background-image: url("/image/hacked.png"); }

.seriousError {
  border-width: 3px; }

擴展選擇器:

@extend 不止擴展類選擇器,還可以擴展任何選擇器,比如 .special.cool, a:hover, 或 a.user[href^=“http://“],例如:

.hoverlink {
  @extend a:hover;
}
a:hover {
  text-decoration: underline;
}

編譯出來:

a:hover, .hoverlink {
  text-decoration: underline; }

再來看一個複雜點的:

.hoverlink {
  @extend a:hover;
}
.comment a.user:hover {
  font-weight: bold;
}

編譯出來的CSS

.comment a.user:hover, .comment .user.hoverlink {
  font-weight: bold; }

多個擴展

所設某個樣式要繼承多個地方的樣式,那麼可以使用 @extend 來繼承多個選擇器或佔位符的樣式,如:

.error {
  border: 1px #f00;
  background-color: #fdd;
}
.attention {
  font-size: 3em;
  background-color: #ff0;
}
.seriousError {
  @extend .error;
  @extend .attention;
  border-width: 3px;
}

編譯出來的CSS

.error, .seriousError {
  border: 1px #f00;
  background-color: #fdd; }

.attention, .seriousError {
  font-size: 3em;
  background-color: #ff0; }

.seriousError {
  border-width: 3px; }

擴展單一選擇器

前面我們知道 %placeholder 不使用@extend顯示調用是不會生成任何樣式代碼。那麼在選擇器中使用佔位符一樣。比如下面的代碼:

#context a%extreme {
  color: blue;
  font-weight: bold;
  font-size: 2em;
}

這段代碼在不調用之前不產生任何代碼,只有通過@extend調用之後才生成代碼:

.notice {
  @extend %extreme;
}

編譯出來的CSS

#context a.notice {
  color: blue;
  font-weight: bold;
  font-size: 2em;
}

4.@at-root

@at-root 從字面上解釋就是跳出根元素。當你選擇器嵌套多層之後,想讓某個選擇器跳出,此時就可以使用 @at-root。來看一個簡單的示例:

.a {
  color: red;

  .b {
    color: orange;

    .c {
      color: yellow;

      @at-root .d {
        color: green;
      }
    }
  }  
}

編譯出來的CSS

.a {
  color: red;
}

.a .b {
  color: orange;
}

.a .b .c {
  color: yellow;
}

.d {
  color: green;
}

5. @debug

@debug 在 Sass 中是用來調試的,當你的在 Sass 的源碼中使用了 @debug 指令之後,Sass 代碼在編譯出錯時,在命令終端會輸出你設置的提示 Bug:

@debug 10em + 12em;

會輸出:

Line 1 DEBUG: 22em

6. @warn

@warn 和 @debug 功能類似,用來幫助我們更好的調試 Sass。如:

@mixin adjust-location($x, $y) {
  @if unitless($x) {
    @warn "Assuming #{$x} to be in pixels";
    $x: 1px * $x;
  }
  @if unitless($y) {
    @warn "Assuming #{$y} to be in pixels";
    $y: 1px * $y;
  }
  position: relative; left: $x; top: $y;
}

具體代碼例子如下

@mixin adjust-location($x, $y) {
  @if unitless($x) {//unitless是內置函數,判斷數值是否有“單位”
    @warn "Assuming #{$x} to be in pixels";
    $x: 1px * $x;
  }
  @if unitless($y) {
    @warn "Assuming #{$y} to be in pixels";
    $y: 1px * $y;
  }
  position: relative; left: $x; top: $y;
}
.botton{
    @include adjust-location(20px, 30);
}


編譯後的css

.botton {
  position: relative;
  left: 20px;
  top: 30px;
}

7.@error

@error 和 @warn、@debug 功能是如出一轍。

@mixin error($x){
  @if $x < 10 {
    width: $x * 10px;
  } @else if $x == 10 {
    width: $x;
  } @else {
    @error "你需要將#{$x}值設置在10以內的數";
  }

}
.test {
  @include error(15);
}

編譯的時候,命令終端會顯示錯誤信息:

你需要將15值設置在10以內的數 on line 7 at column 5

發佈了44 篇原創文章 · 獲贊 68 · 訪問量 32萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章