網站導覽

語法

串接層

生成規則的串接層選擇、原生規則的歸屬、重要性與規則順序。

本頁目錄

除非 class 明確選取另一個支援的串接層,Master CSS 都會將生成的樣式規則放進 utilities。受管理的主題宣告使用 theme。原生 CSS 則保留原本撰寫的串接層,包括透過 @apply 展開 mixin 的原生規則。

本頁定義串接層的歸屬與生成規則的排序。若要覆寫元件或透過 DevTools 診斷,請見指南中的串接層。

建立順序

基底樣式表透過 @master/css/base.css 提供,也包含在完整的 @master/css 匯入中;它會宣告:

@layer theme, base, defaults, components, utilities;

請在其他規則建立這些串接層之前載入它。CSS 會依首次出現的順序決定層次,後來的順序宣告無法重新排列已建立的串接層。生成的串接層區塊本身不會加入這段宣告。

一般宣告與重要宣告

這些串接層的一般宣告互相競爭時,utilities 的優先順序最高,theme 最低。不屬於任何串接層的一般作者規則優先於所有這些層。!important 會反轉串接層之間的順序,並讓層內的重要規則優先於無層的重要規則。此處比較的是作者樣式表內部的順序,並非涵蓋來源、行內樣式、動畫與轉場的完整階層串接。請見 CSS 串接層排序。

重要性會反轉串接層優先順序

比較作者樣式表中重要性相同的宣告。無層的一般規則優先於具名串接層;具名串接層的重要規則優先於無層的重要規則。

文字說明
  1. 基底樣式表依序宣告 theme、base、defaults、components 與 utilities。
  2. 作者樣式表的一般宣告從 theme 到 utilities 優先順序逐步提高,無層宣告則高於所有具名串接層。
  3. 作者樣式表的重要宣告則朝相反方向提高優先順序:theme 是這些串接層中最強的,無層的重要宣告最弱。
  4. 串接層優先順序先於選擇器權重比較。圖中分別比較相同重要性的兩組宣告,不是將一般宣告與重要宣告或其他階層串接來源互相比較。

串接層優先順序先於選擇器權重判定,因此權重更高的元件選擇器,無法單靠權重勝過一般 utility 宣告。同一層內的宣告仍受其他階層串接條件影響,請見選擇器權重。

串接層歸屬

串接層生成內容原生 CSS 慣例
theme保留在 :root, :host 下的受管理 token 宣告Token 預設值
base帶有 @layer(base) 的 class正規化與文件基底
defaults帶有 @layer(defaults) 的 class廣泛的專案或內容預設樣式
components帶有 @layer(components) 的 class可重用的產品 class
utilities一般 utilities、組合樣式與原生宣告 class;明確的 @layer(utilities)區域 utility 規則

原生 CSS 欄說明的是預期職責,不是限制 CSS 在某個串接層可使用哪些屬性。defaults 是專案串接層,不是瀏覽器的使用者代理樣式表。token 相依項目的傳遞方式請見變數與模式。

選取生成規則的串接層

class 後綴只接受以下四個串接層名稱:

@layer(base)@layer(defaults)@layer(components)@layer(utilities)

這個後綴會選取整個生成 class 所屬的串接層,不會建立子層,也不會移動該 class 相依的主題變數。請將它與其他後綴一起放在結尾 ! 之前。

形式結果
block@layer(defaults)display 規則放進 defaults
block@layer(base)@layer(base)一個 base 層規則;允許重複相同選擇
block@layer(base)@layer(utilities)CLASS_SYNTAX_ERROR:一個 class 不能選取不同串接層
block@layer(theme)UNKNOWN_CONDITION:theme 不是生成樣式規則可選的串接層
block@layer(custom)UNKNOWN_CONDITION:任意原生串接層名稱不能作為 class 後綴目標

專案自有的串接層與子層請使用原生 @layer 語法。它們的順序遵循原生 CSS;class 後綴不會註冊新的串接層名稱。

選取樣式串接層不會移動其 token

兩條串接層帶顯示輸出的歸屬,並非以位置呈現完整的階層串接比較。

文字說明
  1. p-md@layer(defaults) 將生成的 padding 宣告輸出到 defaults 串接層。
  2. 其 --spacing-md 相依項目仍會輸出在 theme 層的 :root,:host 下。@layer(defaults) 選取的是 class 規則的串接層,不是相依項目的串接層。

Base 與 defaults

base 層的後代規則可以建立結構基底:

<body class="(list-style:none)_ul@layer(base)">…</body>
產生的 CSS
@layer base {  .\(list-style\:none\)_ul\@layer\(base\) ul {    list-style: none  }}

defaults 層的後代規則可以建立程式碼排版,並讓區域元件與 utility 的選擇保有較高優先順序:

<body class="font-mono_:is(code,pre)@layer(defaults)">…</body>
產生的 CSS
@layer theme {  :root,  :host {    --font-family-mono: var(--font-mono, ui-monospace), SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace  }}@layer defaults {  .font-mono_\:is\(code\,pre\)\@layer\(defaults\) :is(code, pre) {    font-family: var(--font-family-mono)  }}

font-mono class 留在 defaults 中,它需要的字型 token 仍在 theme。選擇器後綴決定哪些後代元素取得宣告,與串接層選擇互相獨立。

預設樣式的優先順序低於區域選擇

這裡的兩個規則都指向第一個段落。段落自己的原生宣告 class 放在 utilities,因此會覆寫文章在 defaults 層的字型大小:

<article class="(font-size:1rem)_p@layer(defaults)">  <p class="(font-size:1.5rem)">24</p>  <p>16</p></article>
產生的 CSS
@layer defaults {  .\(font-size\:1rem\)_p\@layer\(defaults\) p {    font-size: 1rem  }}@layer utilities {  .\(font-size\:1\.5rem\) {    font-size: 1.5rem  }}

原生規則與受管理的 utilities

位於 @layer components 內的原生 class 仍是原生 CSS。它預設會被傳遞,並遵循該層內的原生來源順序,不會取得 Master 的選擇器或條件後綴。@prune native 控制未使用的原生選擇器是否可以移除。

此例的 .btn 宣告 inline-flex,flex 則產生一般 utility 宣告。建立基底順序後,按鈕會使用 display: flex:

@layer components {  .btn {    display: inline-flex;  }}
<button type="button" class="btn flex">Save</button>
產生的 CSS
@layer components {  .btn {    display: inline-flex;  }}@layer utilities {  .flex {    display: flex  }}

隨需產生的 @utility 則會註冊受管理的 class。它的一般輸出屬於 utilities,但可以透過後綴選取另一個支援的串接層:

@utility flow {  display: grid;  gap: var(--spacing-md);}
<div class="flow@layer(defaults)">Example</div>
產生的 CSS
@layer theme {  :root,  :host {    --spacing-md: 1rem  }}@layer defaults {  .flow\@layer\(defaults\) {    display: grid;    gap: var(--spacing-md)  }}

utility 定義與原生規則保留方式,請見 Utilities 與 mixins。

Mixin 展開會保留所在的串接層

原生規則內的 @apply 會在出現的位置展開宣告,不會將該規則移到 utilities:

@mixin --inset {  padding: 1.5rem;}@layer components {  .card {    @apply --inset;  }}
<div class="card p(8)">Example</div>
產生的 CSS
@layer components {  .card {    padding: 1.5rem  }}@layer utilities {  .p\(8\) {    padding: calc(8 * 1px)  }}

建立基底順序後,utility 的 8px 內距會勝過元件的 1.5rem。若沒有外層串接層,原生 .card 規則就不屬於任何層,其一般內距宣告會優先於一般 utility。

串接層區塊必須放在 mixin 主體與 @apply 內容之外,這些位置不接受串接層區塊。串接層決定整個生成規則的歸屬,不是用來包覆部分宣告。

同一串接層內的優先順序

HTML 中的 class 順序不會決定誰優先。Master CSS 為生成規則提供穩定順序,再由瀏覽器對相符宣告套用階層串接。在可比較的串接層、選擇器與條件情境中,生成規則依下列順序排列:

  1. 包含多個宣告,或包含內部選擇器與條件的組合樣式。

  2. 單一宣告 utilities,包括固定、以 token 提供值,以及直接值的 utilities。

  3. 原生宣告 class。

單一宣告 utilities 依屬性家族與涵蓋範圍排序:單一邊或軸的規則會排在整個家族之後。屬性與作用範圍相同時,具名 token 值會排在直接值之前。重要性、選擇器權重與條件仍會參與判定;直接值不會在所有情況下都勝過其他作用範圍或串接層中的 token。

以下範例使用預設集、基底串接層宣告,以及 16px 的根元素字型大小。競爭的宣告指向同一個元素,而且條件都相符。

競爭的 class 或規則結果原因
p-md p(8),順序不限padding: 8px相同屬性與作用範圍中,直接值排在 token 之後
p(8) (padding:2rem),順序不限padding: 2rem原生宣告排在單一宣告 utility 之後
m-md mt(0),順序不限上外距 0;其他外距 1rem單一邊排在整個外距家族之後
b(2) bt(0) b-solid b-red-60上邊寬 0;其他邊寬 2px;紅色實線邊框寬度、樣式與色彩是獨立家族
p-md! p(8)padding: 1rem重要性先於值來源排序
p-md! p(8)!padding: 8px重要性相同;直接值排在 token 之後
p(8)@layer(base) p(12)padding: 12px一般 utilities 優先於 base
p(8)@layer(base)! p(12)!padding: 8px重要宣告會反轉串接層優先順序
無層的 .outside { padding: 32px; } 與 p(8)padding: 32px無層的一般宣告優先於層內宣告
components 層的 padding: 24px !important 與 p(8)!padding: 24px重要宣告之間,以較早的串接層優先

串接層內的原生規則會保留撰寫時的順序,上述生成 utility 的排序不會重新排列它們。宣告重疊時請檢查輸出的 CSS,並使用程式碼 lint,在撰寫時找出衝突的 class。