新手也可以輕鬆玩轉 SASS - @mixin and @include
技術文章

新手也可以輕鬆玩轉 SASS - @mixin and @include

#CSS #SASS #SCSS #mixin #include

Grace Huang

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);
  }

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

  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 時,只要修改定義的地方即可,不用再大費周章的到處修改(也省去很多複製貼上),是不是變得更有效率呢?

推薦學習
網頁設計入門必修-cover

網頁設計入門必修

本課程將從零基礎開始,循序漸進帶領你踏入網頁設計的世界。內容分為兩大部分: 第一部分聚焦 HTML,你將學會如何把腦海中的網頁構想,轉換成瀏覽器能理解的語意化標籤,建立出清晰的結構與內容。 第二部分則專注於 CSS,帶你掌...

查看課程