串接層
以 utility 覆寫共用元件,並找出規則衝突、未分層 CSS 與重要性造成的影響。
本頁目錄
#概述
局部調整不必提高選擇器權重。將共用元件規則放在 components 層,再由個別實例的 utility 覆寫需要改變的屬性。
較後的層決定局部內距
在這些一般宣告之間,utilities 的優先順序高於 components。HTML 中的 class 順序不會改變結果。
文字說明
- 建立順序. 預設樣式集依序宣告 theme、base、defaults、components、utilities。
- 比較宣告. 原生 collection-card 元件提供 1.5rem 內距。同一元素上的 p-sm 則在較後的 utilities 層提供 0.75rem 內距。
- 觀察結果. 在這些一般宣告之間,utility 會生效。根字級為 16px 時,計算後的內距是 12px。
#局部覆寫元件樣式
CSS 串接層會先決定各組宣告的順序,再比較選擇器權重。將可重用的元件樣式放在 components 層;當某個實例需要不同的值時,再加上 utility:
共用元件,局部調整
@layer components { .collection-card { padding: 1.5rem; border: 1px solid var(--color-line-divider); border-radius: var(--radius-lg); background-color: var(--color-surface-raised); }}<div class="grid-cols(1) gap-lg wrap-anywhere"> <article class="collection-card"> <h2 class="m(0) text-lg font-regular">Release notes</h2> <p class="mt-xs mb(0) text-sm fg-text-muted">Updates for your workspace.</p> </article> <article class="collection-card p-sm"> <h2 class="m(0) text-lg font-regular">Release notes</h2> <p class="mt-xs mb(0) text-sm fg-text-muted">Updates for your workspace.</p> </article></div>產生的 CSS
@layer components { .collection-card { border: 1px solid var(--color-line-divider); border-radius: var(--radius-lg); background-color: var(--color-surface-raised); padding: 1.5rem; }}@layer theme { :root, :host { --color-zinc-40: oklch(68.6% .0028 265); --color-zinc-60: oklch(48.6% .003 265); --color-zinc-90: oklch(24.6% .0022 265) } :root, :host { --color-surface-raised: light-dark(var(--color-white), var(--color-zinc-90)); --color-line-divider: light-dark(oklch(0% 0 none / .12), oklch(100% 0 none / .12)); --color-text-muted: light-dark(var(--color-zinc-60), var(--color-zinc-40)) } :root, :host { --color-white: oklch(100% 0 none) } :root, :host { --font-weight-regular: 400; --font-size-sm: .875rem; --font-size-lg: 1.125rem; --text-sm: var(--font-size-sm); --text-sm--line-height: 1.5; --text-sm--letter-spacing: 0; --text-lg: var(--font-size-lg); --text-lg--line-height: 1.5; --text-lg--letter-spacing: 0; --radius-lg: .5rem; --spacing-xs: .5rem; --spacing-sm: .75rem; --spacing-lg: 1.5rem }}@layer utilities { .text-lg { font-size: var(--text-lg); line-height: var(--text-lg--line-height, normal); letter-spacing: var(--text-lg--letter-spacing, normal) } .text-sm { font-size: var(--text-sm); line-height: var(--text-sm--line-height, normal); letter-spacing: var(--text-sm--letter-spacing, normal) } .grid-cols\(1\) { display: grid; grid-template-columns: repeat(1, minmax(0, 1fr)) } .fg-text-muted { color: var(--color-text-muted) } .font-regular { font-weight: var(--font-weight-regular) } .gap-lg { gap: var(--spacing-lg) } .m\(0\) { margin: calc(0 * 1px) } .mt-xs { margin-top: var(--spacing-xs) } .mb\(0\) { margin-bottom: calc(0 * 1px) } .wrap-anywhere { overflow-wrap: anywhere } .p-sm { padding: var(--spacing-sm) }}預設樣式集為一般宣告建立以下順序:
@layer theme, base, defaults, components, utilities;p-sm utility 的優先順序高於元件的內距宣告,與這個 class 在 HTML 屬性中的位置無關。串接規則說明了這個順序及其適用範圍。
這個 utility 只會改變內距,不會取代元件或移除其他宣告。因此,小幅的局部調整不需要新增元件變體,也不需要使用 !important。
#將原生規則放在正確的層
未放在任何層中的一般規則,優先順序高於具名層內的一般規則。如果 utility 已經編譯卻看不出效果,請檢查是否有未分層的元件規則:
/* This normal rule wins over a layered padding utility. */.collection-card { padding: 1.5rem;}如果這個共用規則應該允許 utility 覆寫,就將它移到 @layer components。不要只為了彌補非預期的分層方式而加上 !important。
未分層規則的優先順序高於一般分層規則
此處比較的是作者樣式中的一般宣告。帶有 !important 的宣告使用不同的層優先順序。
文字說明
圖中先將 components 排在 utilities 之前,再將未分層的規則獨立放在兩者上方。最後生效的內距來自該未分層規則。
分層不會取代串接的其他規則。是否帶有 !important 會先於一般層的優先順序決定結果,而且 !important 會反轉層與層之間的順序。行內宣告、動畫與轉場也各有其優先順序。這些規則請參閱 CSS 串接規範;預設樣式集的層順序則見 Master CSS 分層規則。
#找出互相競爭的宣告
- 在瀏覽器開發者工具中選取元素,到計算後的樣式中找到該屬性,再追查實際生效的宣告。
- 確認兩個規則都選中該元素,而且各自的條件都成立。
- 檢查每個宣告所屬的層,也要留意分層之外的原生 CSS。
- 加入局部覆寫之前,先將廣泛適用的預設樣式放回原本規劃的層。
- 如果只看層順序仍無法解釋結果,就繼續檢查
!important與原生串接規則。
透過正常的 Master CSS 入口載入基礎樣式表。生成的規則會包含所屬的 layer 區塊,但不會自行加入基礎層順序的宣告。
將 collection-card p-sm 對調成 p-sm collection-card 無法解決問題:HTML 中的 class 順序不會控制串接結果。如果同一條件下的兩個 utility 互相重疊,可用程式碼檢查找出衝突,再決定要保留哪個宣告。



