網站導覽

指令

Utilities 與 mixins

定義隨需產生的 utilities、可重用的 mixins,以及使用串接層的原生樣式。

本頁目錄

@utility 註冊按需生成的 class。@mixin 為可重複使用的 CSS 本體命名;@apply 在呼叫處展開它。原生選擇器仍是一般 CSS。重複使用樣式說明如何選擇形式;本頁定義其語法與取代規則。

@utility

在頂層明確宣告 class 形式:

@utility card-layout {  display: grid;  gap: var(--spacing-md);  &:hover {    outline: 1px solid currentColor;  }}@utility col-gap-(--spacing) {  column-gap: var(--spacing);}@utility grid-cols(--cols <integer>) {  display: grid;  grid-template-columns: repeat(var(--cols), minmax(0, 1fr));}

在標記中使用 card-layout、col-gap-sm 與 grid-cols(3)@sm。標頭決定定義註冊的是固定 class、token 模式或函式。每種形式只註冊該形式,token 模式不會同時建立函式呼叫。增加宣告或受支援的巢狀規則,不會改變註冊形式。

utility 名稱與 token 前綴不能包含 _,因為 _ 在 class 中開始後代選擇器;這類定義會在來源處回報錯誤。token 鍵可以含 _:它仍是可供 var() 使用的合法變數,但不會產生裸 token class 或補全。mixin 名稱、自訂屬性與原生樣式表 class 仍可使用 _。

註冊與預設集

主題提供 token,utility 定義決定這些 token 能產生哪些 class。匯入 "@master/css" 取得完整預設集;明確組合樣式表時,也可搭配自己的 token 載入 "@master/css/utilities.css"。

家族索引提供完整 token 與屬性對應。固定 utility與直接數值列出各自的註冊。它們都使用本頁所述的相同定義形式。

token 模式

模式有一個尾端佔位符。參數指定 token 命名空間,固定部分指定 class 前綴。未標示型別的佔位符綁定 token 值:

@utility p-(--spacing) {  padding: var(--spacing);}@utility m-(--spacing) {  margin: var(--spacing);}@utility fg-(--color) {  color: var(--color);}@utility size-(--spacing) {  width: var(--spacing);  height: var(--spacing);}

p-md 綁定 var(--spacing-md);size-md 在兩個宣告中使用該參照。一般 token 保留由瀏覽器求值的參照,inline token 則將宣告值代入一次。未知 token 不會建立 class。值模式接受數字與 Unicode 鍵,包含內含 -- 的鍵。

<string> 佔位符綁定 token 鍵,可用來明確參照伴隨值:

@theme {  --text-hero: var(--font-size-5xl);  --text-hero--line-height: 1.15;  --text-hero--letter-spacing: -.03em;}@utility text-(--text <string>) {  font-size: var(ident("--text-" var(--text)));  line-height: var(ident("--text-" var(--text) "--line-height"), normal);  letter-spacing: var(ident("--text-" var(--text) "--letter-spacing"), normal);}

text-hero 綁定字串 "hero",且必須存在對應的主要 token。含 -- 的伴隨鍵不會建立 class;缺少伴隨值時使用原本撰寫的備援值。ident() 會靜態摺疊為一般 CSS 識別名稱。命名空間來自參數,因此 @utility type-(--text <string>) 使用相同 token,搭配不同 class 前綴。token 佔位符不接受預設值或其他型別。

共用前綴可以明確提供數個命名空間:

@utility font-(--font-family) {  font-family: var(--font-family);}@utility font-(--font-size) {  font-size: var(--font-size);}@utility font-(--font-weight) {  font-weight: var(--font-weight);}

font-sans、font-sm 與 font-bold 各自選取唯一含有該鍵的命名空間。鍵若存在於多個分支,使用時會回報 AMBIGUOUS_TOKEN,且不產生 CSS。請改用不同鍵,或 (font-size:var(--font-size-brand)) 這類原生宣告。這項規則同樣適用字串鍵組合樣式與多宣告本體。否定與不透明度只在選定唯一分支後才檢查。

固定 class 優先於模式:保留的是完整 class 拼法,不是 token 鍵。因此即使存在 --text-center,text-center 仍設定 text-align;fg-solid、b-solid/.5 與 -mx-auto 則仍可使用名為 solid 或 auto 的 token。模式採用最長前綴;所選家族內若沒有 token,就回報錯誤,不再嘗試較短前綴。參數命名空間不同的 token 模式可共用前綴。較後模式會完整取代解碼後前綴與命名空間皆相同的定義,包含參數模式、本體、來源與相依關係。靜態與函式註冊則各自獨立取代同形式、同名稱的定義。

負值與不透明度適用於直接值子集:一個未標示型別的佔位符,以及一個完整值恰為 var(--parameter) 的原生宣告。-m-md 將數值間距 token 轉為負值;-p-md 無效,因為 padding 不支援負值。fg-red/.5 為色彩 token 套用不透明度,範圍為零到一。這些能力不延伸到一般多宣告或字串鍵組合樣式。

兩個符合的命名空間不會產生兩個宣告

此自訂主題中兩個 token 鍵都存在。Master CSS 必須先選出唯一命名空間,才會生成 class。

文字說明
  1. 有 --font-family-brand: monospace 與 --font-size-brand: 2rem 時,font-brand 符合兩個預設 font- 家族。
  2. 結果為 AMBIGUOUS_TOKEN,且該 class 不產生 CSS;分支不會合併。
  3. 請用不同鍵,或 (font-size:var(--font-size-brand)) 這類明確的原生宣告。

靜態引數

函式 utility 與 mixin 接受位置參數:未標示型別、<integer>、<number>、<string> 或 <custom-ident>。靜態預設值用冒號指定,例如 --cols <integer>: 2。數字必須是數值字面值;格線數量與跨度必須為正整數。字串引數必須加引號。

@utility pair(--size) {  width: var(--size);  height: var(--size);}

使用 pair(2rem)。一般函式引數必須能在靜態階段確定。若函式或 mixin 恰有一個未標示型別、無預設值的參數,且只有一個完整值恰為 var(--parameter) 的原生宣告,也接受符號式 var() 運算式。呼叫端的參照會原樣保留,交由瀏覽器求值。其他函式會拒絕外部 var()、attr() 與相依瀏覽器的引數。已知的外層參數可透過 var(--parameter) 轉送。

A parameter utility

@utility pair(--size) { width: var(--size); height: var(--size); } @safelist 'pair(2rem)';
產生的 CSS
@layer utilities {  .pair\(2rem\) {    width: 2rem;    height: 2rem  }}

靜態組合樣式引數不同於即時 CSS 值

圖中的 pair utility 有兩個宣告。另一項單參數、單宣告的符號式參照例外,不適用於此。

文字說明
  1. @utility pair(--size) { width: var(--size); height: var(--size); } 接受 pair(2rem) 的已知引數,並綁定到兩個宣告。
  2. 此組合樣式拒絕 pair(var(--size)),因為引數依賴瀏覽器。需要維持即時變化的值,請用明確的原生宣告 class。
  3. (width:var(--size)) 為瀏覽器保留變數參照,只改變寬度。若也需要高度,請另外加入高度宣告。

@mixin 與 @apply

Master 編譯實驗性 CSS Mixins 規範的靜態子集。定義採用雙連字號名稱,且必須是不帶條件、位於樣式表層級的規則。mixin 提供 CSS 重複使用,不會註冊 Master class。

@mixin --caption {  font-size: var(--font-size-sm);  line-height: 1.5;}.caption {  color: currentColor;  @apply --caption;  font-weight: 600;}@utility caption {  @apply --caption;}

@apply 在原生規則、utility 或另一個 mixin 內接受一個 mixin 呼叫,不接受 utility 名稱或 class 清單。展開發生在原本的宣告位置,並保留重複宣告、重要性、選擇器、條件與 URL 所有權。

參數可用於套用的元素上,包含 &:hover 與條件包裝。跨元素使用參數、重新賦值、選擇器或條件插值、遞迴定義、多載、@private 與不支援的型別,都會回報編譯錯誤。此靜態子集未實作依賴瀏覽器的參數求值、私有屬性或通用函式。

mixin 在呼叫位置展開

插入位置前後的相同行保持對齊。選擇器、宣告順序與外層串接層仍由呼叫端擁有。

文字說明
  1. --caption mixin 提供 font-size: 14px 與 line-height: 1.5。
  2. 在 .caption 內,@apply --caption 展開於 color: currentColor 與 font-weight: 600 之間。
  3. 展開不會註冊 class,也不會將原生規則移至生成串接層。重複宣告與撰寫順序都會保留。

內容與 class 包裝

使用 @contents 標示呼叫端的宣告或巢狀規則插入可重複使用包裝的位置。

@mixin --card-wide() {  @container card (width >= 40rem) {    @contents {      display: grid;    }  }}.card {  @apply --card-wide {    gap: 1rem;  }}

@contents; 插入提供的內容。@contents { … } 只在呼叫省略區塊時提供備援內容。明確的空 @apply --card-wide {} 會抑制備援。每個 contents 位置插入一次區塊,保留宣告、重複值與巢狀規則。沒有 @contents 的 mixin 會忽略提供的區塊。

省略 contents 區塊與空區塊不同

mixin 包含 @contents { display: grid; }。呼叫處的大括號區分刻意留空與省略區塊。

文字說明
  1. @apply --panel; 省略 contents 區塊,使用 display: grid 備援。
  2. @apply --panel {} 提供空區塊,抑制備援,因此本例不新增宣告。
  3. @apply --panel { display: flex; } 提供自己的內容來取代備援,兩個 display 宣告不會合併。

提供的內容保留呼叫端參數綁定,即使經由巢狀套用轉送也是如此。備援內容使用定義 mixin 的綁定。一般自訂屬性保留原生 CSS 階層串接行為。允許有限的巢狀呼叫;遞迴定義與超出展開深度或節點上限都屬於錯誤。

@mixin --hocus {  &:is(:hover, :focus-visible) {    @contents;  }}@utility emphasis {  color: red;  display: block;}
<button class="(color:red)@apply(--hocus)">Save</button><div class="grid-cols(3)@apply(--card-wide)"></div><div class="emphasis@apply(--hocus)!"></div>

@apply(--name(...)) 接受靜態引數。多個 @ 包裝由左向右巢狀套用:(color:red)@apply(--a)@apply(--b) 將 --a 放在 --b 外層。utility 將所有宣告作為一個區塊提供,因此包裝自身的宣告每個 class 只輸出一次。選擇器後綴保留原本位置;結尾 ! 將每個展開宣告標為重要。class 頭部與除 @apply 外的條件後綴決定 class 排序:每個外層條件分支都是獨立排序的一條規則;mixin 內部選擇器與條件留在輸出文字中,不會讓 class 移到較後排序層級,展開也保留原始順序。若展開未新增宣告、選擇器或條件,便與單一宣告 utility 一起排序;若頭部是 (property:value),則與原生宣告一起排序。其餘展開以組合樣式排序。檢查與衝突分析使用展開後的規則。

未使用的定義、捨棄的 contents 與未使用的備援區塊,不會保留 token 或關鍵影格。已交付原生 @apply 仍透過 emitted-globals 契約作為資源根節點。宣告位置與相對 URL 保留其定義或呼叫檔案。

包裝決定呼叫端宣告的位置

醒目插槽與插入宣告位於選擇器邊界內的同一位置。包裝控制宣告套用在哪裡。

文字說明
  1. @mixin --hocus { &:is(:hover, :focus-visible) { @contents; } } 定義含有明確 contents 插槽的選擇器包裝。
  2. underline@apply(--hocus) 將 text-decoration-line: underline 提供給插槽。輸出規則在任一狀態都可比對 class 所屬元素。
  3. 圖示結果以 & 簡寫跳脫後的 class 所屬元素,讓位置容易閱讀;生成 CSS 仍保留完整所屬元素。

完整定義取代

較後的定義會取代同一註冊的完整本體,不會合併宣告。同名靜態 utility 與函式 utility 是獨立註冊。token 模式只取代解碼後前綴與命名空間皆相同的分支。

@utility badge {  color: red;  padding: 1rem;}@utility badge {  color: blue;}

badge 現在只輸出 color: blue。先前的 padding 與其相依關係已移除。

較後定義完整取代註冊

兩個定義註冊相同的靜態 utility。第二個完整取代第一個,原有的 padding 也不再保留。這是生成前的定義取代,不是兩條 CSS 規則在階層串接中競爭。

文字說明
  1. 第一個靜態 badge 定義含有 color: red 與 padding: 1rem。
  2. 較後的靜態 badge 定義只含 color: blue,並完整取代第一個定義。
  3. 使用 badge 會生成一條含 color: blue 的規則。先前的 padding 與其相依關係不會留下。
  4. 靜態與函式註冊仍彼此獨立。token 模式只取代前綴與命名空間相同的分支;mixin 則取代完整具名定義。

mixin 名稱只有一個最終定義,包含參數清單、本體與相依關係。空定義仍維持註冊。向前的巢狀呼叫依最終註冊表解析;不提供參數多載。

靜態名稱與函式各自獨立註冊

路徑表達註冊身分。名稱相同不會讓兩個定義變成多載或合併本體。

文字說明
  1. @utility badge { display: inline-block; } 註冊靜態 badge class。@utility badge(--inset) { padding: var(--inset); } 註冊獨立函式。
  2. 將靜態定義改為 display: block 會改變 badge,但 badge(8px) 仍寫入 padding: 8px。
  3. 取代影響的是同形式、同名稱的完整本體。函式不是靜態 class 的備援。

定義作用範圍與匯入

@theme、@utility、@mixin、@custom-media 與 @custom-container 是頂層定義,在串接層或條件包裝內註冊會產生錯誤。mixin 本體可包含宣告、巢狀選擇器、受支援的原生條件、巢狀 @apply 與 @contents。串接層位置由呼叫端決定。

來源掃描、安全清單、引擎 API 與執行階段 DOM 變更中的 class,都是使用根節點。已交付原生 CSS 中的 @apply 也是根節點;未使用 utility 或 mixin 內,或未交付 @reference 樣式表內的 @apply 則不是。相依收集在參數綁定與 ident() 摺疊後進行。已使用 token 保留有序宣告與遞移相依關係。靜態 token 即使沒有使用端,也維持根節點。移除最後一個根節點會釋放資源;原生 CSS 資源則透過 emittedGlobals 保持固定。

執行階段 manifest 保留未使用定義,供未來 DOM class 使用。按需生成處理的是 CSS 與資源輸出。原生 CSS 修剪仍須明確啟用;關鍵影格與其宣告檔案共用原生保留和修剪政策。帶限定的匯入只能包含原生 CSS。定義請透過不帶限定的匯入或參照載入。

原生屬性優先順序

原生 (property:value) class 的 CSS 屬性意義獨立於 utility 註冊。在相同條件下,單一宣告 utility 與原生宣告 class 可以覆寫組合樣式的一部分。完整排序與覆寫規則請見宣告與值。

原生預設樣式

將原生預設樣式寫在 @layer defaults 中。

原生元件

將原生元件選擇器寫在 @layer components 中。

@layer components {  .button {    display: inline-flex;    padding: var(--spacing-md);    &:focus-visible {      outline: 2px solid currentColor;    }  }}

原生規則依樣式表匯入圖交付。utility 定義註冊 class 名稱;mixin 定義透過 @apply 提供 CSS 重複使用。兩者都在編譯期間使用,只有被使用時才輸出 CSS。

Sass 互通

使用 Sass 時,請將 CSS mixin 定義放在 .css 檔案。目前 Dart Sass 為未來 CSS 支援保留 @mixin --name,並拒絕將它視為 Sass mixin;請見 Sass 相容性公告。SCSS 檔案可在 Master CSS 編譯前,透過插值輸出原生 at-rule:

@#{'mixin'} --card {  padding: 1rem;}.card { @apply --card; }

這是 Sass 插值,不是額外的 Master CSS 語法。Sass @include 與 CSS @apply 仍是獨立結構。

主題選擇器包裝

原生選擇器與查詢啟用主題覆寫。mixin 可以提供對應的 class 條件:

@mixin --ocean {  &:where([data-theme="ocean"], [data-theme="ocean"] *) {    @contents;  }}

使用 (color:white)@apply(--ocean)。要指向 shadow host 時,請明確加入 :host(...) 選擇器。