Skip to content

Sass 混入的參數:預設值、關鍵字引數與任意參數

Sass 混入的參數、預設值與任意參數

沒有參數的 混入 只能產出固定的樣式。加上參數之後,同一段邏輯就能依呼叫者給的值產出不同結果,這才是混入真正有威力的地方。

基本參數

scss
@mixin square($size) {
  width: $size;
  height: $size;
}

.avatar { @include square(48px); }
.icon   { @include square(24px); }
css
.avatar { width: 48px; height: 48px; }
.icon { width: 24px; height: 24px; }

預設值

參數名稱後面加冒號與值:

scss
@mixin button($bg: #2965f1, $radius: 4px) {
  background: $bg;
  border-radius: $radius;
}

.btn         { @include button; }                  // 兩個都用預設
.btn-danger  { @include button(#e03131); }         // 只改第一個
.btn-pill    { @include button(#2965f1, 999px); }  // 兩個都給

有預設值的要排在後面

@mixin box($radius: 4px, $bg) 是不合法的。沒有預設值的參數必須排在前面。

關鍵字引數

參數一多,位置就記不住了。呼叫時直接寫參數名稱:

scss
@mixin button($bg: #2965f1, $color: #fff, $radius: 4px, $padding: 8px 16px) {
  background: $bg;
  color: $color;
  border-radius: $radius;
  padding: $padding;
}

// 只想改圓角,前面兩個維持預設
.btn-pill {
  @include button($radius: 999px);
}

用位置引數的話得寫成 @include button(#2965f1, #fff, 999px),前兩個明明沒要改,卻得重複一次。

三個以上的參數就該用關鍵字引數

可讀性差很多。@include button($radius: 999px) 一眼看得懂,@include button(#2965f1, #fff, 999px, 8px 16px) 得回頭查定義。

null 做選擇性輸出

值為 null 的宣告 整行都不會輸出,這讓「有給才寫」變得很簡單:

scss
@mixin box($padding: 16px, $shadow: null, $border: null) {
  padding: $padding;
  box-shadow: $shadow;
  border: $border;
}

.a { @include box; }
.b { @include box($shadow: 0 2px 8px rgba(0, 0, 0, 0.1)); }
css
.a { padding: 16px; }
.b { padding: 16px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); }

不必寫 @if 就達成選擇性輸出,資料型別 那篇有更多 null 的特性。

任意參數

最後一個參數加三個點,就會把剩下的引數全收成一個 list

scss
@mixin shadow($shadows...) {
  box-shadow: $shadows;
}

.card {
  @include shadow(0 1px 2px #0001, 0 4px 12px #0002);
}
css
.card {
  box-shadow: 0 1px 2px #0001, 0 4px 12px #0002;
}

適合 box-shadowtransitionbackground 這類本來就接受多組值的屬性。

展開引數

反過來,把一個 list 展開成多個引數也是三個點:

scss
@mixin edge($top, $right, $bottom, $left) {
  inset: $top $right $bottom $left;
}

$corners: 0, auto, auto, 0;

.badge {
  @include edge($corners...);
}

map 也能展開成 關鍵字引數

scss
$config: (bg: #e03131, radius: 999px);

.btn {
  @include button($config...);  // 等同 $bg: #e03131, $radius: 999px
}

檢查參數

寫給團隊用的混入,值得花三行把錯誤擋在編譯期:

scss
@use "sass:meta";

@mixin square($size) {
  @if meta.type-of($size) != number {
    @error "square() 的 $size 必須是數字,收到 #{meta.inspect($size)}。";
  }

  width: $size;
  height: $size;
}

.a { @include square(48); }     // ✅
.b { @include square("48px"); } // ❌ 編譯時就報錯,訊息很清楚

錯誤訊息的寫法見 除錯

常見問題

參數的預設值怎麼寫?

在參數名稱後面加冒號與值,例如寫成 $size: 16px。有預設值的參數必須排在沒有預設值的參數後面,呼叫時可以省略。

參數很多時怎麼避免搞錯順序?

用關鍵字引數,呼叫時直接寫參數名稱與值。這樣順序就不重要,也能跳過中間有預設值的參數,只指定你要改的那幾個,可讀性比一串位置引數好很多。

怎麼接收數量不固定的參數?

在最後一個參數後面加三個點,它就會收集剩下所有引數成為一個 list。用在 box-shadowtransition 這類本身就接受多組值的屬性上特別合適。

怎麼讓某個宣告在沒給參數時不要輸出?

把該參數的預設值設成 null。值為 null 的宣告整行都不會出現在產出的 CSS 裡,不必額外寫條件判斷就達成選擇性輸出。

延伸閱讀