Sass 系列教學:
繼上篇基本的變數介紹之後,本篇來談談 Sass 中的巢狀(nested rules) 、命名空間(namespaces) 、引用(import) 等語法。
巢狀結構 (Nested Rules)
假設在 HMTL 文件中有以下的結構:
<div id="main">
<p>
Look at
<a class="red box" href="">this link</a>
</p>
</div>
以往在撰寫 CSS 碼時,如果想針對結構內的階層關係進行設定時,就可能會空格分隔來表達,例如:
#main p {
color: #777;
width: 50%;
}
#main p .redbox {
background-color: red;
color: white;
}
如果 HTML 文件的階層結構簡單,那麼這種寫法其實沒有什麼問題;一旦階層結構複雜,那麼就可能出現很多 CSS 區塊都是針對某一個區塊內的元素而撰寫的設定,結果就會形成又臭又長的 CSS 碼。因此 Sass 也可以用巢狀的結構來表達 CSS 的階層關係,像上述的 CSS 範例,可以 Sass 寫成:
#main p {
color: #777;
width: 50%;
.redbox {
background-color: red;
color: white;
}
}
善用這樣的巢狀結構寫法,可以讓你的 Sass 更簡潔、更具閱讀性喔!
p.s. 官方建議,如果能夠使用簡單的結構語法,就不要使用太多巢狀結構,否則網頁載入速度會變慢,建議最多不要超過 3 層或 4 層
用 & 符號參照巢狀結構的父選取器 (Referencing Parent Selectors)
CSS 中有定義一些 pseudo-classes (或稱偽類、準類別),被使用來為元素增加一些特效,如 :hover
, :link
, :visited
等這些以冒號(:)開頭的類別名稱。例如把滑鼠移到某個網頁連結時,連結會變色的 CSS 語法:
a {
font-weight: bold;
text-decoration: none;
}
a :hover {
color:#FF00FF;
}
上述其實還是一種巢狀的結構,只是都作用到同一個元素(例如範例的 a 元素)上。這樣的情況就能夠用對 :hover
使用 &
符號來代表其作用的父選取器,所以上述的 CSS 範例的 Sass 就可以寫成:
a {
font-weight: bold;
text-decoration: none;
&:hover {
color:#FF00FF;
}
}
更多關於 Parent Selectors
命名空間 (Namespaces)
在 CSS 中,有定義很多屬性都是相同字串開頭 ,例如 font-family, font-size, font-weight 這些都是以 font 開頭,因此在 Sass 中就定義了命名空間的寫法,例如以下的 CSS 碼:
.serif-font {
font-family: serif;
font-size: 25em;
font-weight: bold;
}
可以用 Sass 的命名空間表達成:
.serif-font {
font: {
family: serif;
size: 25em;
weight: bold;
}
}
此外,命名空間也可以有自己的設定喔!例如,設定命名空間 font 的長寬為 2px / 3px
:
.serif-font {
font: 2px / 3px {
family: serif;
size: 25em;
weight: bold;
}
}
上述範例會被編譯成:
.serif-font {
font: 2px/3px;
font-family: serif;
font-size: 25em;
font-weight: bold;
}
@import
如果一個專案撰寫了很多個 scss / sass 檔案,就可以透過 @import
引用這些 scss/sass 檔案。 @import
對實務上有很大的幫助,因為可以把常用的、慣用的 CSS 碼放在不同的 scss/ sass 檔案內,達到模組化的功用!
語法:
@import "scss_file1", "scss_file2";
p.s. @import
不需加副檔名
p.s. 如果 scss/sass 檔名前加上底線(例如 _index.scss
),就代表這個檔案不需要 compile 成 CSS 檔案,且 @import
時檔名並不用加底線。
@extend
繼承,這是我所能想到的最好的解釋了。以往如果有相同的 CSS 屬性,是無法用繼承的方式進行屬性的複製與改寫,得重新撰寫 CSS 碼才行。現在透過 Sass 的 @extend 就能夠進行屬性的繼承了!
語法:
@extend selector;
例如 Sass 官方提供的範例:
.error {
border: 1px #f00;
background-color: #fdd;
}
.seriousError {
@extend .error;
border-width: 3px;
}
.seriousError
繼承了 .error
的樣式,所以會被編譯成:
.error, .seriousError {
border: 1px #f00;
background-color: #fdd;
}
.seriousError {
border-width: 3px;
}
p.s. 每一個 Sass 區塊並沒有限定能夠使用 @extend
幾次,使用多重繼承也是可以的,只是要注意屬性覆蓋的問題,根據 CSS 的原則,前後屬性如相同,以最後出現的為準。
此外,在 Sass 中,有一種 extend only 的用法,如果在選取器(selector)名稱後加上 %
符號及名稱,就代表此一選取器只提供 @extend
繼承,且 %
符號及 %
後的名稱,會被繼承者的 #
或 .
符號所取代,而定義 extend only 的 Sass
區塊並不會被 Sass 編譯進 CSS 中。
例如:
a%ext-only {
color: red;
}
.notice {
@extend %ext-only;
}
就會被 Sass 編譯成:
a.notice {
color: red;
}
以上的用法要注意,不可與定義 extend only 的 Sass 區塊內的元素衝突!例如把 .notice
改成 h1.notice
就會產生錯誤,因為原始可接受的定義是 extend-only-selector#id
或 extend-only-selector.class
,以上述範例來說就是 a#id
, a.class
。
!optional
在使用 @extend
時,後方的選取器(selector)必須實際存在或沒有任何錯誤存在,如果想 @extend
一個不存在的選取器或有錯誤暫時不想修正,可以在 @extend
最後面加上 !optional
標籤即可,例如前述的 extend only
的錯誤就可以用
!optional
來修正。
語法:
@extend selector !optional ;
@mixin
@mixin
就像其字面意思一樣,可以用來混在 Sass 區塊中。因此它的作用其實很像函數,只要定義好 @mixin
之後,就可以不斷重複利用。
語法 1:
@mixin mixin-name { ... }
語法 2:
@mixin 可以像函數一樣使用參數。
@mixin mixin-name($arg1, $arg2, ...) { ... }
語法 3:
語法3的意義其實跟語法2一模一樣,只是語法 3 會更好閱讀跟理解參數的意思。
@mixin mixin-name($arg1: value1, $arg2: value2, ...) { ... }
以下是使用 @mixin
的範例:
@mixin clear-fix {
display: inline-block;
}
@include
定義好 @mixin
之後,要使用 @mixin
的方法就是使用 @include
。
語法 1:
@include mixin-name;
語法 2:
@include mixin-nam(arg1, arg2, ...);
例如調用先前定義好的 mixin clear-fix :
p {
@include clear-fix;
}
更多 @include
@content
@content
也經常與 @mixin
一起使用,因為 @content
的作用是能夠讓 @mixin
傳入一整個 CSS 區塊的用法。
範例 1:
@mixin colors {
width: 1000px;
@content;
}
.title {
@inclue colors { background-color: blue; }
}
範例1的寫法其實,就是將 { background-color: blue; }
一整個區塊傳進 @mixin
colors 的 @content
內。其結果就像以下的 CSS 碼:
.title {
width: 1000px;
background-color: blue;
}
@content
的用法雖然便利,不過也要注意區域變數的問題,例如以下的範例 2,我們可能會誤以為 @include colors { color: $color; }
傳入的 $color
是 blue ,但事實上此 $color
與 @mixin colors($color: blue)
的 $color
不同, @include colors { color: $color; }
的 $color
取決於位於 .title
內的區域變數或全域變數。
範例 2:
$color: white;
@mixin colors($color: blue) {
background-color: $color;
@content;
}
.title {
width: 1000px;
@include colors { color: $color; }
}
範例 2 的結果如下:
.title {
width: 1000px;
background-color: blue;
color: white;
}
@function
@function
用法幾乎與 @mixin
相同,不過它多了 @return
可以使用回傳值!
語法:
@function func($arg1, $arg2, ...) {
@return $variable ;
}
範例:
@function double($n) {
@return $n * 2;
}
$width: 20;
.cell-width {
width: double($width);
}
上述範例會被編譯成:
.cell-width {
width: 40;
}
@if
@if
判斷式,請直接看範例!
範例:
$type: ie;
p {
@if $type == ie { color: blue; }
@elif $type == chrome { color: green; }
@else { color: black; }
}
@for
這也沒什麼好說明的,可以直接看範例。
語法:
@for $i from $number1 through $number2 {
...
}
範例:
@for $variable from 1 through 3 {
.item-#{$1} { width: 100px * $i; }
}
範例結果:
.item-1 { width: 100px; }
.item-2 { width: 200px; }
.item-3 { width: 300px; }
@each
語法:
@each $variable in <list>
...
}
範例:
@each $variable in 1, 2, 3 {
.item-#{$variable} { width: 100px * $variable; }
}
範例結果:
.item-1 {
width: 100px;
}
.item-2 {
width: 200px;
}
.item-3 {
width: 300px;
}
@while
直接看範例:
$i: 6;
@while $i > 0 {
.item-#{$i} { width: 2em * $i; }
$i: $i - 2;
}
範例結果:
.item-6 {
width: 12em;
}
.item-4 {
width: 8em;
}
.item-2 {
width: 4em;
}
@debug
& @warn
Sass 也提供一些 Debug 的技巧,例如 @debug
, @warn
,兩者的用法相同,可以在開發過程善用它,以減少除錯的次數。例如可以在 Sass 檔內添加一行:
@debug 10em + 12em;
在編譯時就會跳出以下的訊息提示:
Line 1 DEBUG: 22em
以上是簡單的 Sass 語法介紹,有興趣者也可以至 Sass