新手也可以輕鬆玩轉 SASS - @mixin and @include
SASS (Syntactically Awesome Stylesheet) 是一種預處理語言 (pre-processing language),透過 SASS 可以更有效、更結構化的產生 CSS,並有助於減少撰寫重複的樣式,讓你的 CSS 更易於維護。今天要跟大家分享的是 SASS 的 @mixin 與 @include。
SASS 提供兩種語法,分別是 SCSS (Sassy CSS),以及 Indented,最大的差別在語法上 {}
、;
、=
的有無,以及前者的副檔名為 .scss
,後者的副檔名為 .sass
,筆者在文章內採用 SCSS 的語法來跟大家分享。
前置準備
範例中我們使用下列工具:
- 編輯器:Visual Studio Code (以下簡稱 VSCode)
- 安裝套件:Live Sass Compiler、Live Server
套件 Live Sass Compiler 安裝完成後,在 VSCode 的右下方有一個 Watch Sass
按鈕,他的功能是將我們撰寫好的 .scss
或 .sass
編譯過後產生 .css
,我們在 html 裡要引入的就是這個被產生出來的 CSS 檔案。
當原來的 Watch Sass
按鈕變成 Watching...
的狀態時,我們還是可以繼續編輯 .scss
或 .sass
,在編輯完成存檔的當下就會自動編譯並更新之前產生的 .css
。 有關 .min.css
、Prefix
的設定,可以參考 Setting Docs 的說明。
套件 Live Server 安裝完成後,在 VSCode 的右下方會出現 Go Live
按鈕,在我們編輯好 HTML 並確實引入 CSS 檔案,存檔後按下該按鈕,會自動在瀏覽器開啟網頁,顯示最新存檔後的畫面。(本篇著重在 SASS 的使用分享,所以先暫時略過畫面的部份囉)
什麼情況需要用到 @mixin、@include?
- 發現自己在 CSS 裡一直寫著重複的樣式。
- 網頁元件可以歸納出共同的特性時 (可能按鈕都有陰影、或是每個文章區塊都有邊框…等等)。
- 認為自己開發網頁 CSS 效率遇到瓶頸,欲尋更好的撰寫效率。
語法
@mixin
- 以
@mixin
開頭,並自定義一個名稱,將需要重複使用的 CSS 放在{ }
裡面。 - 定義好的
@mixin
是可以重複使用的。 - 可以在名稱後面加
()
,放入參數、預設值做進階的使用。 - 參數名稱以
$
開頭。
@mixin example_base {
... // 定義 CSS
}
@mixin example_advanced($parameter1, $parameter2) {
... // 定義 CSS
}
@include
- 搭配
@mixin
,我們在@mixin
定義好 CSS,再透過@include
呼叫使用。 - 若定義的
@mixin
有設定參數,那麼在呼叫使用的時候,就要傳入相對應的引數。
selector1 {
@include example_base; // 呼叫使用在 @mixin 定義的 CSS
... // 這個 selector 的其他 CSS
}
selector2 {
@include example_advanced(argument1, argument2); // 呼叫使用在 @mixin 定義的 CSS
... // 這個 selector 的其他 CSS
}
範例一:基本用法
- 假設在網頁中,我們每個按鈕
.button
的樣式統一都是邊框加 5px 的圓角再加一點點陰影,每個.article
要邊框加 5px 的圓角但不要陰影,每張圖片.image
也都邊框加 5px 的圓角再加一點點陰影好了,這些 “邊框加 5px 圓角,或許再加一點點陰影” 的樣式,我們就可以把 CSS 拉出來做@mixin
,並在需要該樣式設定的時候使用@include
:
@mixin rounded-border {
border: 2px #333 solid;
border-radius: 5px;
}
@mixin shadow {
box-shadow: 1px 2px 2px #666;
}
.article {
@include rounded-border;
}
.button {
@include rounded-border;
@include shadow;
}
.image {
@include rounded-border;
@include shadow;
}
- 編譯過後的 CSS 呈現如下:
.article {
border: 2px #333 solid;
border-radius: 5px;
}
.button {
border: 2px #333 solid;
border-radius: 5px;
-webkit-box-shadow: 1px 2px 2px #666;
box-shadow: 1px 2px 2px #666;
}
.image {
border: 2px #333 solid;
border-radius: 5px;
-webkit-box-shadow: 1px 2px 2px #666;
box-shadow: 1px 2px 2px #666;
}
- 將統一的樣式抽出來寫成 @mixin 的好處是,如果該樣式需要做調整的話,那麼只需要改 @mixin 這一個地方就好了,不用再一個一個找(或搜尋)。
- Live Sass Compiler 可以設定 Prefix,在編譯過後的 CSS 會自動加上。
範例二:使用參數
- 假設在網頁中,我們有一個遮罩覆蓋的效果,在
.avatar
、.product-image
這兩個 class 都需要用到它,差別在遮罩透明度不一樣,那麼我們可以在 SASS 檔案裡這樣寫:
// 定義遮罩覆蓋的基本屬性
@mixin cover($opacity_value) {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
opacity: $opacity_value; // opacity 的值由傳進來的參數決定
}
.avatar {
@include cover(0.9); // 呼叫的時候帶入數值
}
.product-image {
@include cover(0.8); // 呼叫的時候帶入數值
}
- 編譯過後的 CSS 呈現如下:
.avatar {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
opacity: 0.9;
}
.product-image {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
opacity: 0.8;
}
範例三:使用參數 + 預設值
- 定義 @mixin 時若有使用參數,在呼叫的時候必須要依序傳入相對應的引數。
- 以範例一的 rounded-border 再作延伸:
/*
在 rounded-border 這個 @mixin 定義中,我們"依序"使用三個參數,並給它預設值:
1. $color: border 的顏色,預設為 #333
2. $line_style: border 的線條樣式,預設為實線
3. $radius: border-radius 預設為 5px
*/
@mixin rounded-border($color: #333, $line_style: solid, $radius: 5px) {
border: 2px $color $line_style;
border-radius: $radius;
}
.article {
// 全部套用預設值,可以不用加 ()
@include rounded-border;
}
.button {
/*依序帶入引數:
$radius 使用預設值,因為是排序在最後一個,可以不用帶入引數
只要依序帶入前面 $color、$line_style 的值即可*/
@include rounded-border(#f00, dashed);
}
.image {
/*依序帶入引數:
$color 使用預設值,因為不是排序在最後一個,若略過它直接帶入第二個值會導致配對錯誤,因此後面帶入的引數必須指定參數名稱*/
@include rounded-border($line_style: dashed, $radius: 3px);
}
註解看起來好像很複雜?這邊有幾點要稍微留意一下:
- @include 的時候必須要依序傳入相對應的引數,講白話就是:"一個蘿蔔一個坑",跳過前面的坑,就要指定後面坑的名字,這樣後面的蘿蔔才不會跳錯坑 XD
- 參數如果一次用太多反而會造成不便,因為自己還要記清楚那些參數的順序、數量,所以在設計 @mixin 時,要考量到使用的彈性跟方便性哦~
- 編譯過後的 CSS 呈現如下:
.article {
border: 2px #333 solid;
border-radius: 5px;
}
.button {
border: 2px #f00 dashed;
border-radius: 5px;
}
.image {
border: 2px #333 dashed;
border-radius: 3px;
}
結論
SASS 讓 CSS 寫起來很像在寫程式,對於沒有程式基礎的使用者來說其實也不需要太擔心, @mixin
的主要用意就是整理會重複使用到的 CSS,需要它的時候就用 @include
把它 “召喚” 出來,需要修改這些大量重複的 CSS 時,只要修改定義的地方即可,不用再大費周章的到處修改(也省去很多複製貼上),是不是變得更有效率呢?