Skip to content

Sass @content:把整段樣式傳進混入

Sass @content 傳入樣式區塊

參數 傳的是值,@content 傳的是 一整段樣式。呼叫 混入 時在後面接一個大括號區塊,混入內部的 @content 就是那段樣式要被放進去的位置。

運作方式

scss
@mixin hover {
  &:hover,
  &:focus-visible {
    @content;   // ← 呼叫者給的樣式會出現在這裡
  }
}

.btn {
  @include hover {
    background: #1b4dc1;
    color: #fff;
  }
}
css
.btn:hover,
.btn:focus-visible {
  background: #1b4dc1;
  color: #fff;
}

混入負責 外殼(選取器、條件),呼叫者負責 內容

最常見的用途:媒體查詢

這是 @content 的招牌用法:

scss
$breakpoints: (
  sm: 576px,
  md: 768px,
  lg: 992px,
);

@mixin respond-to($name) {
  $size: map.get($breakpoints, $name);

  @media (min-width: $size) {
    @content;
  }
}
scss
.card {
  padding: 16px;

  @include respond-to(md) {
    padding: 24px;
  }

  @include respond-to(lg) {
    padding: 32px;
  }
}
css
.card { padding: 16px; }
@media (min-width: 768px) { .card { padding: 24px; } }
@media (min-width: 992px) { .card { padding: 32px; } }

好處是斷點的 數值只存在一個地方。設計改版把 md 從 768px 調成 800px,改 map 一行,全站生效。完整實作見 響應式 mixin 實作

主題與狀態

同樣的模式可以包裝任何「條件外殼」:

scss
@mixin dark {
  @media (prefers-color-scheme: dark) {
    @content;
  }

  :root[data-theme="dark"] & {
    @content;
  }
}

.card {
  background: #fff;

  @include dark {
    background: #1a1a1a;
  }
}

一次處理系統偏好與手動切換兩種情況,呼叫端只寫一段樣式。多主題的完整做法見 多主題切換

區塊在呼叫處求值

這是最容易誤會的地方,傳進去的樣式 在呼叫的地方求值,不是在混入內部:

scss
@mixin wrapper {
  $inner: 999px;   // 混入內部的區域變數

  .box {
    @content;
  }
}

$outer: 16px;

.page {
  @include wrapper {
    padding: $outer;   // ✅ 看得到呼叫處的變數
    // margin: $inner; // ❌ Error:看不到混入內部的變數
  }
}

換句話說:變數的查找是照著程式碼寫在哪裡,不是照著它被展開到哪裡。

using 把值交給區塊

真的需要把混入內部的值傳給區塊時,用 @content()using

scss
@use "sass:map";

$themes: (
  light: (bg: #fff, text: #333),
  dark:  (bg: #1a1a1a, text: #f5f5f5),
);

@mixin each-theme {
  @each $name, $theme in $themes {
    [data-theme="#{$name}"] & {
      @content($theme);   // 把這一輪的主題傳出去
    }
  }
}

.card {
  @include each-theme using ($theme) {
    background: map.get($theme, bg);
    color: map.get($theme, text);
  }
}
css
[data-theme="light"] .card { background: #fff; color: #333; }
[data-theme="dark"] .card { background: #1a1a1a; color: #f5f5f5; }

using 的參數是位置引數

@content($a, $b) 對應 using ($x, $y),順序決定對應關係,不能用名稱指定。

兩個提醒

一、沒寫 @content 的話區塊會被丟掉。

scss
@mixin box {
  padding: 16px;
  // 忘了寫 @content
}

.card {
  @include box {
    color: red;   // 這段靜靜消失,不會報錯
  }
}

樣式莫名不見時,先回頭看混入裡有沒有 @content

二、@content 可以出現多次。 上面 dark 混入的例子就寫了兩次,同一段樣式會被複製到兩個地方,這是刻意的,但要記得它會讓產出變成兩份。

常見問題

@content 最常見的用途是什麼?

包裝媒體查詢。把斷點的條件寫在混入裡,呼叫時只要給斷點名稱與一段樣式,就不必在每個元件重複寫 min-width 的數值,斷點要調整時也只需改一處。

傳進去的樣式在哪個作用範圍求值?

在呼叫的地方,不是在混入定義的地方。所以區塊裡用得到呼叫處看得見的變數,卻用不到混入內部的區域變數。要把混入內部的值交給區塊,得用 @content 帶參數搭配 using

using 是做什麼的?

它讓混入可以把值傳給傳入的樣式區塊。混入裡寫 @content 加上括號與引數,呼叫端就用 using 加括號宣告接收的變數名稱,區塊內部即可使用那個值。

混入沒寫 @content 但呼叫時帶了區塊會怎樣?

那段樣式會被靜靜丟掉,不會報錯也不會輸出。查不出樣式為何消失時,記得回頭確認混入定義裡有沒有 @content

延伸閱讀