新手也可以輕鬆玩轉 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.cssPrefix 的設定,可以參考 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);
  }

註解看起來好像很複雜?這邊有幾點要稍微留意一下:

  1. @include 的時候必須要依序傳入相對應的引數,講白話就是:"一個蘿蔔一個坑",跳過前面的坑,就要指定後面坑的名字,這樣後面的蘿蔔才不會跳錯坑 XD
  2. 參數如果一次用太多反而會造成不便,因為自己還要記清楚那些參數的順序、數量,所以在設計 @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 時,只要修改定義的地方即可,不用再大費周章的到處修改(也省去很多複製貼上),是不是變得更有效率呢?