Sass入門:第三章


1.聲明變量

  Sass聲明變量以美元符號"$"開頭。例如:

$width : 300px;

上面的例子中,Sass的變量包括三個部分:

  (1)聲明變量的符號"$"

  (2)變量

  (3)賦予變量的值

再看一個定義按鈕顏色的例子:

$brand-primary : darken(#428bca, 6.5%) !default; // #337ab7
$btn-primary-color : #fff !default;
$btn-primary-bg : $brand-primary !default;
$btn-primary-border : darken($btn-primary-bg, 5%) !default;

2.普通變量與默認變量

(1)普通變量

定義之后可以在全局范圍內使用:

$fontSize : 12px; body { font-size : $fontSize;  
}

編譯后的CSS代碼:

body { font-size : 12px;
}

(2)默認變量

sass的默認變量僅需要在值后面加上!default即可:

$baseLineHeight : 1.5 !default; body { line-height : $baseLineHeight;
}

編譯后的CSS代碼:

body { line-height : 1.5;  
}

Sass的默認變量一般是用來設置默認值,然后根據需求來覆蓋的,覆蓋的方式很簡單,只需要在默認變量之前重新聲明下變量即可。

$baseLineHeight : 2; $baseLineHeight : 1.5 !default; body { line-height : $baseLineHeight;
}

編譯后的CSS代碼:

body { line-height : 2;
}

3.變量的調用

  在Sass中聲明了變量之后,就可以在需要的地方調用變量。調用變量的方法也非常簡單。

比如在定義了變量:

$brand-primary : darken(#428bca, 6.5%) !default; // #337ab7
$btn-primary-color: #fff !default;
$btn-primary-bg : $brand-primary !default;
$btn-primary-border : darken($btn-primary-bg, 5%) !default;

在按鈕button中調用,可以按下面的方式調用:

.btn-primary { background-color: $btn-primary-bg; color: $btn-primary-color; border: 1px solid $btn-primary-border;
}

編譯出來的CSS:

.btn-primary { background-color: #337ab7; color: #fff; border: 1px solid #2e6da4;
}

4.全局變量局部變量

(1)全局變量與局部變量

  從3.4版本開始,Sass已經可以處理作用域的概念,並通過創建一個新的局部變量來代替。

來看一下代碼例子:

//SCSS $color: orange !default;//定義全局變量(在選擇器、函數、混合宏...的外面定義的變量為全局變量) .block { color: $color;//調用全局變量 } em { $color: red;//定義局部變量 a { color: $color;//調用局部變量 } } span { color: $color;//調用全局變量 }

CSS的結果:

//CSS .block { color: orange;
} em a { color: red;
} span { color: orange;
}

可以看出,全局變量就是定義在元素外部的變量,如下代碼:

$color : orange !default;

$color就是一個全局變量,而定義在元素內部的變量,比如$color:red;就是一個局部變量

除此之外,Sass現在還提供一個!global參數。!global和!default對於定義變量都是很有幫助的。

(2)全局變量的影子

  當在局部方位內(選擇器內、函數內、混合宏內...)聲明一個已經存在於全局范圍內的變量時,局部變量就成為了全局變量的影子。基本上,局部變量只會在局部范圍內覆蓋全局變量

  上面例子中的em選擇器內的變量$color就是一個全局變量的影子

//SCSS $color: orange !default;//定義全局變量 .block { color: $color;//調用全局變量 } em { $color: red;//定義局部變量(全局變量 $color 的影子) a { color: $color;//調用局部變量 } }

(3)什么時候聲明變量?

  ▶該值至少重復出現了兩次;

  ▶該值至少可能會被更新一次;

  ▶該值所有的表現都與變量有關(非巧合)

4.嵌套-選擇器嵌套

  Sass提供了選擇器嵌套的功能,選擇器嵌套為樣式表的作者提供了一個通過局部選擇器相互嵌套實現全局選擇的方法,Sass 的嵌套分為三種:

  ▶選擇器嵌套
  ▶屬性嵌套
  ▶偽類嵌套

(1)選擇器嵌套

假設我們有一段這樣的結構:

<header>
<nav>
    <a href=“##”>Home</a>
    <a href=“##”>About</a>
    <a href=“##”>Blog</a>
</nav>
<header>

想選中 header 中的 a 標簽,在寫 CSS 會這樣寫:

nav a { color:red;
} header nav a { color:green;
}

那么在 Sass 中,就可以使用選擇器的嵌套來實現:

nav { a { color: red; header & { color:green;
    } } }

(2)屬性嵌套

  Sass 中還提供屬性嵌套,CSS 有一些屬性前綴相同,只是后綴不一樣,比如:border-top/border-right,與這個類似的還有 margin、padding、font 等屬性。假設你的樣式中用到了:

.box { border-top: 1px solid red; border-bottom: 1px solid green;
}

在 Sass 中我們可以這樣寫:

.box { border: { top: 1px solid red; bottom: 1px solid green;
  } }

(3)偽類嵌套

其實偽類嵌套和屬性嵌套非常類似,只不過他需要借助"&"符號一起配合使用。

.clearfix{ &:before, &:after { content:""; display: table;
  } &:after { clear:both; overflow: hidden;
  } }

編譯出來的 CSS:

clearfix:before, .clearfix:after { content: ""; display: table;
} .clearfix:after { clear: both; overflow: hidden;
}

(4)避免選擇器嵌套:

  ▶選擇器嵌套最大的問題是將使最終的代碼難以閱讀。開發者需要花費巨大精力計算不同縮進級別下的選擇器具體的表現效果。
  ▶選擇器越具體則聲明語句越冗長,而且對最近選擇器的引用(&)也越頻繁。在某些時候,出現混淆選擇器路徑和探索下一級選擇器的錯誤率很高,這非常不值得。

 5.混合宏--聲明混合宏

  如果你的整個網站中有幾處小樣式類似,比如顏色,字體等,在 Sass 可以使用變量來統一處理,那么這種選擇還是不錯的。但當你的樣式變得越來越復雜,需要重復使用大段的樣式時,使用變量就無法達到我們目了。這個時候 Sass 中的混合宏就會變得非常有意義。

(1)聲明混合宏

▶不帶參數的混合宏:

在 Sass 中,使用"@mixin"來聲明一個混合宏。如:

 

@mixin border-radius{ -webkit-border-radius: 5px; border-radius: 5px;
}

 

  其中 @mixin 是用來聲明混合宏的關鍵詞,有點類似 CSS 中的 @media、@font-face 一樣。border-radius 是混合宏的名稱。大括號里面是復用的樣式代碼。

▶帶參數的混合宏:

除了聲明一個不帶參數的混合宏之外,還可以在定義混合宏時帶有參數,如:

@mixin border-radius($radius:5px){ -webkit-border-radius: $radius; border-radius: $radius;
}

▶復雜的混合宏:

  上面是一個簡單的定義混合宏的方法,當然, Sass 中的混合宏還提供更為復雜的,你可以在大括號里面寫上帶有邏輯關系,幫助更好的做你想做的事情,如:

@mixin box-shadow($shadow...) { @if length($shadow) >= 1 { @include prefixer(box-shadow, $shadow); } @else{ $shadow:0 0 4px rgba(0,0,0,.3); @include prefixer(box-shadow, $shadow); } }

  這個 box-shadow 的混合宏,帶有多個參數,這個時候可以使用" "來替代。簡單的解釋一下,當 $shadow 的參數數量值大於或等於"1"時,表示有多個陰影值,反之調用默認的參數值" 0 0 4px rgba(0,0,0,.3) "。

(2)調用混合宏

  在 Sass 中通過 @mixin 關鍵詞聲明了一個混合宏,那么在實際調用中,其匹配了一個關鍵詞"@include"來調用聲明好的混合宏。例如在你的樣式中定義了一個圓角的混合宏"border-radius" :

@mixin border-radius{ -webkit-border-radius: 3px; border-radius: 3px;
}

在一個按鈕中要調用定義好的混合宏"border-radius",可以這樣使用:

button { @include border-radius; }

這個時候編譯出來的 CSS:

button { -webkit-border-radius: 3px; border-radius: 3px;
}

6.混合宏的參數

Sass 的混合宏有一個強大的功能,可以傳參,那么在 Sass 中傳參主要有以下幾種情形:

(1)傳一個不帶值的參數

在混合宏中,可以傳一個不帶任何值的參數,比如:

@mixin border-radius($radius){ -webkit-border-radius: $radius; border-radius: $radius;
}

在混合宏"border-radius"中定義了一個不帶任何值的參數"$radius"。

在調用的時候可以給這個混合宏傳一個參數值

.box { @include border-radius(3px); }

這里表示給混合宏傳遞了一個"border-radius"的值為"3px"。

編譯出來的 CSS:

.box { -webkit-border-radius: 3px; border-radius: 3px;
}

(2)傳一個帶值的參數

在 Sass 的混合宏中,還可以給混合宏的參數傳一個默認值,例如:

@mixin border-radius($radius:3px){ -webkit-border-radius: $radius; border-radius: $radius;
}

  在混合宏"border-radius"傳了一個參數"$radius",而且給這個參數賦予了一個默認值"3px"。

  假設你的頁面中的圓角很多地方都是"3px"的圓角,那么這個時候只需要調用默認的混合宏"border-radius":

.btn { @include border-radius; }

編譯出來的 CSS:

.btn { -webkit-border-radius: 3px; border-radius: 3px;
}

 但有的時候,頁面中有些元素的圓角值不一樣,那么可以隨機給混合宏傳值,如:

.box { @include border-radius(50%); }

編譯出來的 CSS:

.box { -webkit-border-radius: 50%; border-radius: 50%;
}

(3)傳多個參數

Sass 混合宏除了能傳一個參數之外,還可以傳多個參數,如:

@mixin center($width,$height){ width: $width; height: $height; position: absolute; top: 50%; left: 50%; margin-top: -($height) / 2; margin-left: -($width) / 2;
}

在混合宏"center"就傳了多個參數。在實際調用和其調用其他混合宏是一樣的:

.box-center { @include center(500px,300px); }

編譯出來 CSS:

.box-center { width: 500px; height: 300px; position: absolute; top: 50%; left: 50%; margin-top: -150px; margin-left: -250px;
}

有一個特別的參數""。當混合宏傳的參數過多之時,可以使用參數來替代,如:

@mixin box-shadow($shadows...){ @if length($shadows) >= 1 { -webkit-box-shadow: $shadows; box-shadow: $shadows;
  } @else { $shadows: 0 0 2px rgba(#000,.25); -webkit-box-shadow: $shadow; box-shadow: $shadow;
  } }

在實際調用中:

.box { @include box-shadow(0 0 1px rgba(#000,.5),0 0 2px rgba(#000,.2)); }

編譯出來的CSS:

.box { -webkit-box-shadow: 0 0 1px rgba(0, 0, 0, 0.5), 0 0 2px rgba(0, 0, 0, 0.2); box-shadow: 0 0 1px rgba(0, 0, 0, 0.5), 0 0 2px rgba(0, 0, 0, 0.2);
}

(4)混合宏的不足

  混合宏在實際編碼中給我們帶來很多方便之處,特別是對於復用重復代碼塊。但其最大的不足之處是會生成冗余的代碼塊。比如在不同的地方調用一個相同的混合宏時,如:

@mixin border-radius{ -webkit-border-radius: 3px; border-radius: 3px;
} .box { @include border-radius; margin-bottom: 5px;
} .btn { @include border-radius; }

示例在".box"和".btn"中都調用了定義好的"border-radius"混合宏。

先來看編譯出來的 CSS:

.box { -webkit-border-radius: 3px; border-radius: 3px; margin-bottom: 5px;
} .btn { -webkit-border-radius: 3px; border-radius: 3px;
}

  上例明顯可以看出,Sass 在調用相同的混合宏時,並不能智能的將相同的樣式代碼塊合並在一起。這也是 Sass 的混合宏最不足之處。

 7.擴展/繼承

  在 Sass 中也具有繼承一說,也是繼承類中的樣式代碼塊。在 Sass 中是通過關鍵詞 "@extend"來繼承已存在的類樣式塊,從而實現代碼的繼承。如下所示:

//SCSS .btn { border: 1px solid #ccc; padding: 6px 10px; font-size: 14px;
} .btn-primary { background-color: #f36; color: #fff; @extend .btn; } .btn-second { background-color: orange; color: #fff; @extend .btn; }

編譯出來之后:

//CSS .btn, .btn-primary, .btn-second { border: 1px solid #ccc; padding: 6px 10px; font-size: 14px;
} .btn-primary { background-color: #f36; color: #fff;
} .btn-second { background-clor: orange; color: #fff;
}

  從示例代碼可以看出,在 Sass 中的繼承,可以繼承類樣式塊中所有樣式代碼,而且編譯出來的 CSS 會將選擇器合並在一起,形成組合選擇器:

.btn, .btn-primary, .btn-second { border: 1px solid #ccc; padding: 6px 10px; font-size: 14px;
}

8.占位符%placeholder

  Sass 中的占位符 %placeholder 功能是一個很強大,很實用的一個功能,可以取代以前 CSS 中的基類造成的代碼冗余的情形。因為 %placeholder 聲明的代碼,如果不被 @extend 調用的話,不會產生任何代碼。來看一個演示:

%mt5 { margin-top: 5px;
} %pt5{ padding-top: 5px;
}

  這段代碼沒有被 @extend 調用,他並沒有產生任何代碼塊,只是靜靜的躺在你的某個 SCSS 文件中。只有通過 @extend 調用才會產生代碼:

//SCSS %mt5 { margin-top: 5px;
} %pt5{ padding-top: 5px;
} .btn { @extend %mt5; @extend %pt5; } .block { @extend %mt5; span { @extend %pt5; } }

譯出來的CSS:

//CSS .btn, .block { margin-top: 5px;
} .btn, .block span { padding-top: 5px;
}

  從編譯出來的 CSS 代碼可以看出,通過 @extend 調用的占位符,編譯出來的代碼會將相同的代碼合並在一起

9.混合宏VS繼承VS占位符

  初學者都常常糾結於這個問題 "什么時候用混合宏,什么時候用繼承,什么時候使用占位符?" 其實他們各有各的優點與缺點,先來看看他們使用效果:

(1)Sass中的混合宏使用

//SCSS中混合宏使用 @mixin mt($var){ margin-top: $var;  
} .block { @include mt(5px); span { display:block; @include mt(5px); } } .header { color: orange; @include mt(5px); span{ display:block; @include mt(5px); } }

編譯出來的CSS:

.block { margin-top: 5px; } .block span { display: block; margin-top: 5px; } .header { color: orange; margin-top: 5px; } .header span { display: block; margin-top: 5px; }

總結:編譯出來的 CSS 清晰告訴了大家,混合宏不會自動合並相同的樣式代碼,如果在樣式文件中調用同一個混合宏,會產生多個對應的樣式代碼,造成代碼的冗余,這也是 CSSer 無法忍受的一件事情。不過混合宏並不是一無事處,它可以傳參數。

個人建議:如果代碼塊中涉及到變量,建議使用混合宏來創建相同的代碼塊。

(2)Sass中的繼承

同樣的,將上面代碼中的混合宏,使用類名來表示,然后通過繼承來調用:

//SCSS 繼承的運用 .mt{ margin-top: 5px;  
} .block { @extend .mt; span { display:block; @extend .mt; } } .header { color: orange; @extend .mt; span{ display:block; @extend .mt; } }

編譯出來的CSS:

.mt, .block, .block span, .header, .header span { margin-top: 5px; }

.block span { display: block; } .header { color: orange; } .header span { display: block; }

總結:使用繼承后,編譯出來的 CSS 會將使用繼承的代碼塊合並到一起,通過組合選擇器的方式向大家展現,比如 .mt, .block, .block span, .header, .header span。這樣編譯出來的代碼相對於混合宏來說要干凈的多,也是 CSSer 期望看到。但是不能傳變量參數。

個人建議:如果代碼塊不需要專任何變量參數,而且有一個基類已在文件中存在,那么建議使用 Sass 的繼承。

(3)占位符

最后來看占位符,將上面代碼中的基類 .mt 換成 Sass 的占位符格式:

//SCSS中占位符的使用 %mt{ margin-top: 5px;  
} .block { @extend %mt; span { display:block; @extend %mt; } } .header { color: orange; @extend %mt; span{ display:block; @extend %mt; } }

編譯出來的CSS:

.block, .block span, .header, .header span { margin-top: 5px; } .block span { display: block; } .header { color: orange; } .header span { display: block; }

總結:編譯出來的 CSS 代碼和使用繼承基本上是相同,只是不會在代碼中生成占位符 mt 的選擇器。那么占位符和繼承的主要區別的,"占位符是獨立定義,不調用的時候是不會在 CSS 中產生任何代碼;繼承是首先有一個基類存在,不管調用與不調用,基類的樣式都將會出現在編譯出來的 CSS 代碼中。"

來看一個表格:

 10.插值#{}

  使用 CSS 預處理器語言的一個主要原因是想使用 Sass 獲得一個更好的結構體系。比如說你想寫更干凈的、高效的和面向對象的 CSS。Sass 中的插值(Interpolation)就是重要的一部分。讓我們看一下下面的例子:

$properties: (margin, padding); @mixin set-value($side, $value) { @each $prop in $properties { #{$prop}-#{$side}: $value; } } .login-box { @include set-value(top, 14px); }

它可以讓變量屬性工作的很完美,上面的代碼編譯成 CSS:

.login-box { margin-top: 14px; padding-top: 14px;
}

這是 Sass 插值中一個簡單的實例。當你想設置屬性值的時候你可以使用字符串插入進來。另一個有用的用法是構建一個選擇器。可以這樣使用:

@mixin generate-sizes($class, $small, $medium, $big) { .#{$class}-small { font-size: $small; } .#{$class}-medium { font-size: $medium; } .#{$class}-big { font-size: $big; } } @include generate-sizes("header-text", 12px, 20px, 40px);

編譯出來的 CSS:

.header-text-small { font-size: 12px; } .header-text-medium { font-size: 20px; } .header-text-big { font-size: 40px; }

一旦你發現這一點,你就會想到超級酷的 mixins,用來生成代碼或者生成另一個 mixins。然而,這並不完全是可能的。第一個限制,這可能會很刪除用於 Sass 變量的插值。

$margin-big: 40px; $margin-medium: 20px; $margin-small: 12px; @mixin set-value($size) { margin-top: $margin-#{$size}; } .login-box { @include set-value(big); }

上面的 Sass 代碼編譯出來,你會得到下面的信息:

error style.scss (Line 5: Undefined variable: "$margin-".)

所以,#{}語法並不是隨處可用,你也不能在 mixin 中調用:

@mixin updated-status { margin-top: 20px; background: #F00;
} $flag: "status"; .navigation { @include updated-#{$flag}; }

上面的代碼在編譯成 CSS 時同樣會報錯:

error style.scss (Line 7: Invalid CSS after "...nclude updated-": expected "}", was "#{$flag};")
幸運的是,可以使用 @extend 中使用插值。例如:

%updated-status { margin-top: 20px; background: #F00;
} .selected-status { font-weight: bold;
} $flag: "status"; .navigation { @extend %updated-#{$flag}; @extend .selected-#{$flag}; }

上面的 Sass 代碼是可以運行的,因為他給了我們力量,可以動態的插入 .class 和 %placeholder。當然他們不能接受像 mixin 這樣的參數,上面的代碼編譯出來的 CSS:

.navigation { margin-top: 20px; background: #F00;
} .selected-status, .navigation { font-weight: bold;
}

 11.注釋

在Sass中有兩種注釋方式:

▶類似CSS的注釋方式:使用 "/*"開頭,"*/"結尾

▶類似JavaScript的注釋方式:使用 "//"

 兩者的區別是:前者會在編譯出來的CSS顯示,而后者在編譯出來的CSS中不顯示。

來看一個示例:

 

//定義一個占位符 %mt5 { margin-top: 5px;
}
/*調用一個占位符*/ .box { @extend %mt5; }

 

編譯出來的CSS:

.box { margin-top: 5px;
}
/*調用一個占位符*/

12.數據類型

  Sass和JavaScript類似,也有數據類型,在Sass中包含以下幾種數據類型:

  ▶ 數字:如123px;

  ▶ 字符串:有引號字符串或無引號字符串,如"foo"、"bar";

  ▶ 顏色:如blue#04a3f9rgba(255,0,0,0.5);

  ▶ 布爾型:如truefalse;

  ▶ 空值:如null;

  ▶值列表:用空格或者逗號分開,如2.5em 1em 0 2emHelvetica , Arial , sans-serif.

  Sass也支持其他CSS屬性值,比如Unicode范圍,或!important聲明。然而,Sass不會特殊對待這些屬性值,一律視為無引號字符串。

13.字符串

SassScript支持兩種字符串類型:

  ▶ 有引號字符串,如"Lucida Grande"、"http://sass-lang.com";

  ▶ 無引號字符串,如 sans-serif bold.

  在編譯CSS文件時不會改變其類型。除了使用#{}插值語句時,有引號字符串被編譯為無引號字符串,這樣方便了在混合指定(mixin)中引用選擇器名。

 

@mixin firefox-message($selector) { body.firefox #{$selector}:before { content: "Hi, Firefox users!";
  } } @include firefox-message(".header");

 

編譯為:

body.firefox .header:before { content: "Hi, Firefox users!"; }

14.值列表

所謂值列表(lists)是指Sass如何處理CSS中:

margin: 10px 15px 0 0

或者:

font-face: Helvetica, Arial, sans-serif

像上面這樣通過空格或者逗號分隔的一系列的值。

事實上,獨立的值也被視為值列表——只包含一個值的值列表。

Sass列表函數賦予了值列表更多功能:

  ▶nth函數( nth function ) 可以直接訪問值列表中的某一項;

  ▶join函數( join function ) 可以將多個值列表連結在一起;

  ▶append函數( append function ) 可以在值列表中添加值;

  ▶@each規則( @each rule ) 則能夠給值列表中的每個項目添加樣式。

  值列表中可以再包含值列表,比如:1px 2px,5px 6px是包含1px 2px與5px 6px兩個值列表的值列表。如果內外兩層值列表使用相同的分隔方式,要用圓括號包裹內層,所以也可以寫成(1px 2px ) (5px 6px)。當值列表被編譯為CSS時,Sass不會添加任何圓括號,因為CSS不允許這么做。(1px 2px) (5px 6px)與1px 2px 5px 6px 在編譯后的CSS文件中是一樣的,但是它們在Sass文件中的意義不同,前者表示包含兩個值的值列表后者表示包含四個值的值列表。

  還可以用()表示空的值列表,這樣不可以直接編譯成CSS,比如編譯font-family : ()時,Sass將會報錯。如果值列表中包含空的值列表或空值,編譯時將清除空值。比如1px 2px () 3px 或 1px 2px null 3px。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM