@mixin 與 @include

Mixin 允許您定義可在整個樣式表中重複使用的樣式。它們讓您可以輕鬆避免使用非語意類別,例如 .float-left,並在程式庫中分發樣式集合。

Mixin 是使用 @mixin at-rule 定義的,其寫法為 @mixin <名稱> { ... }@mixin 名稱(<參數...>) { ... }。Mixin 的名稱可以是任何不以 -- 開頭的 Sass 識別符號,並且可以包含任何陳述式,除了頂層陳述式之外。它們可以用於封裝可放入單個樣式規則的樣式;它們可以包含自己的樣式規則,這些規則可以嵌套在其他規則中或包含在樣式表的頂層;或者它們也可以僅用於修改變數。

Mixin 使用 @include at-rule 包含到目前的上下文中,其寫法為 @include <名稱>@include <名稱>(<參數...>),其中包含要包含的 Mixin 的名稱。

程式碼遊樂場

SCSS 語法

@mixin reset-list {
  margin: 0;
  padding: 0;
  list-style: none;
}

@mixin horizontal-list {
  @include reset-list;

  li {
    display: inline-block;
    margin: {
      left: -2px;
      right: 2em;
    }
  }
}

nav ul {
  @include horizontal-list;
}
程式碼遊樂場

Sass 語法

@mixin reset-list
  margin: 0
  padding: 0
  list-style: none


@mixin horizontal-list
  @include reset-list

  li
    display: inline-block
    margin:
      left: -2px
      right: 2em




nav ul
  @include horizontal-list

CSS 輸出

nav ul {
  margin: 0;
  padding: 0;
  list-style: none;
}
nav ul li {
  display: inline-block;
  margin-left: -2px;
  margin-right: 2em;
}











💡 小知識

Mixin 名稱,如同所有 Sass 的識別符號,視連字號和底線為相同。這表示 reset-listreset_list 都指向同一個 mixin。這是 Sass 早期遺留下來的設計,當時它允許在識別符號名稱中使用底線。當 Sass 加入支援連字號以符合 CSS 的語法後,為了讓遷移更容易,兩者被設為等效。

參數參數永久連結

Mixin 也可以接受參數,這允許每次呼叫它們時自訂其行為。參數在 @mixin 規則中,mixin 名稱之後,以括號括住的變數名稱列表指定。然後,mixin 必須以相同數量的參數,以SassScript 表達式的形式引入。這些表達式的值在 mixin 的主體中作為對應的變數提供。

程式碼遊樂場

SCSS 語法

@mixin rtl($property, $ltr-value, $rtl-value) {
  #{$property}: $ltr-value;

  [dir=rtl] & {
    #{$property}: $rtl-value;
  }
}

.sidebar {
  @include rtl(float, left, right);
}
程式碼遊樂場

Sass 語法

@mixin rtl($property, $ltr-value, $rtl-value)
  #{$property}: $ltr-value

  [dir=rtl] &
    #{$property}: $rtl-value



.sidebar
  @include rtl(float, left, right)

CSS 輸出

.sidebar {
  float: left;
}
[dir=rtl] .sidebar {
  float: right;
}





💡 小知識

參數列表也可以有尾隨逗號!這可以更容易避免在重構樣式表時出現語法錯誤。

選用參數選用參數永久連結

通常,mixin 宣告的每個參數都必須在引入該 mixin 時傳遞。但是,您可以透過定義一個預設值來讓參數變成選用的,如果未傳遞該參數,則會使用該預設值。預設值使用與變數宣告相同的語法:變數名稱,後跟冒號和SassScript 表達式。這使得定義彈性的 mixin API 變得容易,可以用於簡單或複雜的方式。

程式碼遊樂場

SCSS 語法

@mixin replace-text($image, $x: 50%, $y: 50%) {
  text-indent: -99999em;
  overflow: hidden;
  text-align: left;

  background: {
    image: $image;
    repeat: no-repeat;
    position: $x $y;
  }
}

.mail-icon {
  @include replace-text(url("/images/mail.svg"), 0);
}
程式碼遊樂場

Sass 語法

@mixin replace-text($image, $x: 50%, $y: 50%)
  text-indent: -99999em
  overflow: hidden
  text-align: left

  background:
    image: $image
    repeat: no-repeat
    position: $x $y

.mail-icon
  @include replace-text(url("/images/mail.svg"), 0)



CSS 輸出

.mail-icon {
  text-indent: -99999em;
  overflow: hidden;
  text-align: left;
  background-image: url("/images/mail.svg");
  background-repeat: no-repeat;
  background-position: 0 50%;
}







💡 小知識

預設值可以是任何 SassScript 表達式,它們甚至可以參考先前的參數!

關鍵字參數關鍵字參數永久連結

引入 mixin 時,除了透過它們在參數列表中的位置傳遞之外,還可以透過名稱傳遞參數。這對於具有多個選用參數的 mixin,或者具有布林值參數(沒有名稱就無法清楚了解其含義)的 mixin 特別有用。關鍵字參數使用與變數宣告選用參數相同的語法。

程式碼遊樂場

SCSS 語法

@mixin square($size, $radius: 0) {
  width: $size;
  height: $size;

  @if $radius != 0 {
    border-radius: $radius;
  }
}

.avatar {
  @include square(100px, $radius: 4px);
}
程式碼遊樂場

Sass 語法

@mixin square($size, $radius: 0)
  width: $size
  height: $size

  @if $radius != 0
    border-radius: $radius



.avatar
  @include square(100px, $radius: 4px)

CSS 輸出

.avatar {
  width: 100px;
  height: 100px;
  border-radius: 4px;
}







⚠️ 注意!

因為任何參數都可以透過名稱傳遞,所以在重新命名 mixin 的參數時要小心…它可能會破壞使用者的程式碼!將舊名稱保留一段時間作為選用參數,並在有人傳遞它時印出警告訊息,以便他們知道要遷移到新的參數,這會很有幫助。

接受任意參數接受任意參數永久連結

有時,讓 mixin 能夠接受任意數量的參數會很有用。如果 @mixin 宣告中的最後一個參數以 ... 結尾,則該 mixin 的所有額外參數都會以列表的形式傳遞給該參數。這個參數稱為參數列表

程式碼遊樂場

SCSS 語法

@mixin order($height, $selectors...) {
  @for $i from 0 to length($selectors) {
    #{nth($selectors, $i + 1)} {
      position: absolute;
      height: $height;
      margin-top: $i * $height;
    }
  }
}

@include order(150px, "input.name", "input.address", "input.zip");






程式碼遊樂場

Sass 語法

@mixin order($height, $selectors...)
  @for $i from 0 to length($selectors)
    #{nth($selectors, $i + 1)}
      position: absolute
      height: $height
      margin-top: $i * $height




@include order(150px, "input.name", "input.address", "input.zip")






CSS 輸出

input.name {
  position: absolute;
  height: 150px;
  margin-top: 0px;
}

input.address {
  position: absolute;
  height: 150px;
  margin-top: 150px;
}

input.zip {
  position: absolute;
  height: 150px;
  margin-top: 300px;
}

接受任意關鍵字參數接受任意關鍵字參數永久連結

參數列表也可以用於接受任意關鍵字參數。meta.keywords() 函式接受一個參數列表,並將傳遞給 mixin 的任何額外關鍵字作為映射(從參數名稱(不包括 $)到這些參數的值)返回。

程式碼遊樂場

SCSS 語法

@use "sass:meta";

@mixin syntax-colors($args...) {
  @debug meta.keywords($args);
  // (string: #080, comment: #800, variable: #60b)

  @each $name, $color in meta.keywords($args) {
    pre span.stx-#{$name} {
      color: $color;
    }
  }
}

@include syntax-colors(
  $string: #080,
  $comment: #800,
  $variable: #60b,
)
程式碼遊樂場

Sass 語法

@use "sass:meta"

@mixin syntax-colors($args...)
  @debug meta.keywords($args)
  // (string: #080, comment: #800, variable: #60b)

  @each $name, $color in meta.keywords($args)
    pre span.stx-#{$name}
      color: $color




@include syntax-colors($string: #080, $comment: #800, $variable: #60b)




CSS 輸出

pre span.stx-string {
  color: #080;
}

pre span.stx-comment {
  color: #800;
}

pre span.stx-variable {
  color: #60b;
}







💡 小知識

如果您從未將參數列表傳遞給 meta.keywords() 函數,則該參數列表將不允許額外的關鍵字參數。這有助於您的 mixin 的呼叫者確保他們沒有意外拼錯任何參數名稱。

傳遞任意參數傳遞任意參數 永久連結

就像參數列表允許 mixin 接收任意位置或關鍵字參數一樣,相同的語法也可用於將位置和關鍵字參數*傳遞*給 mixin。如果您在 include 的最後一個參數傳遞一個列表後加上 ...,其元素將被視為額外的 positional 參數。同樣地,加上 ... 的 map 將被視為額外的 keyword 參數。您甚至可以同時傳遞兩者!

程式碼遊樂場

SCSS 語法

$form-selectors: "input.name", "input.address", "input.zip" !default;

@include order(150px, $form-selectors...);
程式碼遊樂場

Sass 語法

$form-selectors: "input.name", "input.address", "input.zip" !default

@include order(150px, $form-selectors...)

💡 小知識

因為 參數列表 會同時追蹤位置和關鍵字參數,您可以使用它一次將兩者傳遞給另一個 mixin。這使得定義 mixin 的別名變得非常容易!

程式碼遊樂場

SCSS 語法

@mixin btn($args...) {
  @warn "The btn() mixin is deprecated. Include button() instead.";
  @include button($args...);
}
程式碼遊樂場

Sass 語法

@mixin btn($args...)
  @warn "The btn() mixin is deprecated. Include button() instead."
  @include button($args...)

內容區塊內容區塊 永久連結

除了接收參數之外,mixin 還可以接收整個樣式區塊,稱為*內容區塊*。Mixin 可以通過在其主體中包含 @content at-rule 來宣告它接收一個內容區塊。內容區塊像 Sass 中的任何其他區塊一樣使用大括號傳入,並且它會被注入到 @content 規則的位置。

程式碼遊樂場

SCSS 語法

@mixin hover {
  &:not([disabled]):hover {
    @content;
  }
}

.button {
  border: 1px solid black;
  @include hover {
    border-width: 2px;
  }
}
程式碼遊樂場

Sass 語法

@mixin hover
  &:not([disabled]):hover
    @content



.button
  border: 1px solid black
  @include hover
    border-width: 2px


CSS 輸出

.button {
  border: 1px solid black;
}
.button:not([disabled]):hover {
  border-width: 2px;
}






💡 小知識

一個 mixin 可以包含多個 @content at-rule。如果有的話,內容區塊將會為每個 @content 分別包含。

⚠️ 注意!

內容區塊是*詞法作用域*的,這表示它只能看到包含 mixin 的作用域中的 局部變數。它看不到在其傳遞到的 mixin 中定義的任何變數,即使它們是在呼叫內容區塊之前定義的。

將參數傳遞給內容區塊將參數傳遞給內容區塊 永久連結

相容性
Dart Sass
自 1.15.0 起
LibSass
Ruby Sass

Mixin 可以通過編寫 @content(<arguments...>) 將參數傳遞給其內容區塊,就像將參數傳遞給另一個 mixin 一樣。編寫內容區塊的使用者可以通過編寫 @include <name> using (<arguments...>) 來接收參數。內容區塊的參數列表的工作方式就像 mixin 的參數列表一樣,而 @content 傳遞給它的參數的工作方式就像將參數傳遞給 mixin 一樣。

⚠️ 注意!

如果 mixin 將參數傳遞給其內容區塊,則該內容區塊*必須*宣告它接受這些參數。這表示最好只按位置(而不是按名稱)傳遞參數,並且這表示傳遞更多參數是一個破壞性變更。

如果您希望在傳遞給內容區塊的資訊方面具有彈性,請考慮傳遞一個包含它可能需要的資訊的 map

程式碼遊樂場

SCSS 語法

@mixin media($types...) {
  @each $type in $types {
    @media #{$type} {
      @content($type);
    }
  }
}

@include media(screen, print) using ($type) {
  h1 {
    font-size: 40px;
    @if $type == print {
      font-family: Calluna;
    }
  }
}
程式碼遊樂場

Sass 語法

@mixin media($types...)
  @each $type in $types
    @media #{$type}
      @content($type)




@include media(screen, print) using ($type)
  h1
    font-size: 40px
    @if $type == print
      font-family: Calluna



CSS 輸出

@media screen {
  h1 {
    font-size: 40px;
  }
}
@media print {
  h1 {
    font-size: 40px;
    font-family: Calluna;
  }
}





縮排 Mixin 語法縮排 Mixin 語法 永久連結

縮排語法 除了標準的 @mixin@include 之外,還有一種特殊的語法用於定義和使用 mixin。Mixin 使用字元 = 定義,並使用 + 包含。雖然這種語法更簡潔,但它也更難一眼理解,建議使用者避免使用它。

程式碼遊樂場

Sass 語法

=reset-list
  margin: 0
  padding: 0
  list-style: none

=horizontal-list
  +reset-list

  li
    display: inline-block
    margin:
      left: -2px
      right: 2em

nav ul
  +horizontal-list

CSS 輸出

nav ul {
  margin: 0;
  padding: 0;
  list-style: none;
}
nav ul li {
  display: inline-block;
  margin-left: -2px;
  margin-right: 2em;
}