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/。
家族索引提供完整 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。
文字說明
- 有 --font-family-brand: monospace 與 --font-size-brand: 2rem 時,font-brand 符合兩個預設 font- 家族。
- 結果為 AMBIGUOUS_TOKEN,且該 class 不產生 CSS;分支不會合併。
- 請用不同鍵,或 (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 有兩個宣告。另一項單參數、單宣告的符號式參照例外,不適用於此。
文字說明
- @utility pair(--size) { width: var(--size); height: var(--size); } 接受 pair(2rem) 的已知引數,並綁定到兩個宣告。
- 此組合樣式拒絕 pair(var(--size)),因為引數依賴瀏覽器。需要維持即時變化的值,請用明確的原生宣告 class。
- (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 在呼叫位置展開
插入位置前後的相同行保持對齊。選擇器、宣告順序與外層串接層仍由呼叫端擁有。
文字說明
- --caption mixin 提供 font-size: 14px 與 line-height: 1.5。
- 在 .caption 內,@apply --caption 展開於 color: currentColor 與 font-weight: 600 之間。
- 展開不會註冊 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; }。呼叫處的大括號區分刻意留空與省略區塊。
文字說明
- @apply --panel; 省略 contents 區塊,使用 display: grid 備援。
- @apply --panel {} 提供空區塊,抑制備援,因此本例不新增宣告。
- @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 保留其定義或呼叫檔案。
包裝決定呼叫端宣告的位置
醒目插槽與插入宣告位於選擇器邊界內的同一位置。包裝控制宣告套用在哪裡。
文字說明
- @mixin --hocus { &:is(:hover, :focus-visible) { @contents; } } 定義含有明確 contents 插槽的選擇器包裝。
- underline@apply(--hocus) 將 text-decoration-line: underline 提供給插槽。輸出規則在任一狀態都可比對 class 所屬元素。
- 圖示結果以 & 簡寫跳脫後的 class 所屬元素,讓位置容易閱讀;生成 CSS 仍保留完整所屬元素。
完整定義取代
較後的定義會取代同一註冊的完整本體,不會合併宣告。同名靜態 utility 與函式 utility 是獨立註冊。token 模式只取代解碼後前綴與命名空間皆相同的分支。
@utility badge { color: red; padding: 1rem;}@utility badge { color: blue;}badge 現在只輸出 color: blue。先前的 padding 與其相依關係已移除。
較後定義完整取代註冊
兩個定義註冊相同的靜態 utility。第二個完整取代第一個,原有的 padding 也不再保留。這是生成前的定義取代,不是兩條 CSS 規則在階層串接中競爭。
文字說明
- 第一個靜態 badge 定義含有 color: red 與 padding: 1rem。
- 較後的靜態 badge 定義只含 color: blue,並完整取代第一個定義。
- 使用 badge 會生成一條含 color: blue 的規則。先前的 padding 與其相依關係不會留下。
- 靜態與函式註冊仍彼此獨立。token 模式只取代前綴與命名空間相同的分支;mixin 則取代完整具名定義。
mixin 名稱只有一個最終定義,包含參數清單、本體與相依關係。空定義仍維持註冊。向前的巢狀呼叫依最終註冊表解析;不提供參數多載。
靜態名稱與函式各自獨立註冊
路徑表達註冊身分。名稱相同不會讓兩個定義變成多載或合併本體。
文字說明
- @utility badge { display: inline-block; } 註冊靜態 badge class。@utility badge(--inset) { padding: var(--inset); } 註冊獨立函式。
- 將靜態定義改為 display: block 會改變 badge,但 badge(8px) 仍寫入 padding: 8px。
- 取代影響的是同形式、同名稱的完整本體。函式不是靜態 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(...) 選擇器。













