網站導覽

語法

選擇器

選擇器的附加方式、關聯元素、清單、字面值編碼與選擇器權重。

本頁目錄

選擇器後綴決定哪個元素或偽元素會套用 class 的宣告。帶有完整 class 的元素是起點:後綴可以檢查該元素、選取相關元素,或同時進行兩者。

本頁定義選擇器的附加方式、編碼、分組與選擇器權重。語法教學說明如何為元件加入 hover 與鍵盤焦點樣式;CSS 選擇器則定義原生比對行為。

附加選擇器

將選擇器接在已註冊的 utility 後方,或原生宣告的右括號之後。條件放在選擇器之後,重要性標記放在最末端:

utility<selector><conditions>!(property:value)<selector><conditions>!

上方角括號內的部分與 ! 是可省略的語法佔位符。例如,underline:hover@sm 會在帶有 class 的元素處於 hover,且檢視區符合 @sm 時套用底線。條件不會改變選擇器指向的元素。

產生的 CSS
@layer utilities {  @media (width >= 52.125rem) {    .underline\:hover\@sm:hover {      text-decoration-line: underline    }  }  @media (width >= 52.125rem) {    .\(text-decoration-thickness\:2px\)\:hover\@sm:hover {      text-decoration-thickness: 2px    }  }}

Master CSS 會在生成的 CSS 選擇器中跳脫完整 class 名稱。.underline\:hover 中的冒號是字面 class 名稱的一部分;後接的 :hover 才是真正的偽類別。HTML 中請像範例一樣,撰寫未跳脫的 class。

比對帶有 class 的元素

沒有組合器時,後綴會為帶有 class 的元素增加條件。underline.active 只會比對 class 清單同時含有 underline.active 與 active 的元素。

<a class="underline.active active" href="/guide/installation">Installation</a>
class帶有 class 的元素須符合的條件
underline.active也帶有 active class
underline#currentID 為 current
underline[data-current]帶有 data-current 屬性
underline:hover符合瀏覽器的 hover 狀態
underline:is(a)是 a 元素
產生的 CSS
@layer utilities {  .underline\#current#current {    text-decoration-line: underline  }  .underline\:is\(a\):is(a) {    text-decoration-line: underline  }  .underline\[data-current\][data-current] {    text-decoration-line: underline  }  .underline\:hover:hover {    text-decoration-line: underline  }  .underline\.active.active {    text-decoration-line: underline  }}

若要檢查同一元素的型別,請用 :is(a) 或 :where(a)。若要選取其子元素,請用 >a 或 >*。直接接在 utility 名稱後的裸標籤名稱,不是獨立的選擇器後綴。

組合條件

相鄰的簡單選擇器描述同一個元素。underline:hover:not([aria-disabled=true]) 要求 hover,並排除 aria-disabled 屬性為 true 的元素;它不會設定或更新該屬性。

產生的 CSS
@layer utilities {  .underline\:hover\:not\(\[aria-disabled\=true\]\):hover:not([aria-disabled=true]) {    text-decoration-line: underline  }}

選擇器會回應 DOM 與瀏覽器狀態,不會建立互動行為。原生屬性與 ARIA 保有各自的語意。尤其 aria-disabled="true" 只描述停用狀態,本身不會阻止啟動操作。

相關元素

組合器會從帶有 class 的元素移向另一個元素。宣告會套用到選擇器末端的元素,而非從帶有 class 的元素繼承而來。

class目標
underline_a任意深度的後代連結
underline>a直接子連結
underline+a下一個同層元素,且該元素為連結
underline~a同一父元素下、位於後方的所有同層連結
underline>*每個直接子元素

_ 編碼選擇器之間的後代空白。HTML 中真正的空白會開始另一個 class。>、+ 與 ~ 保留 CSS 原生意義。

產生的 CSS
@layer utilities {  .underline\+a + a {    text-decoration-line: underline  }  .underline\>\* > * {    text-decoration-line: underline  }  .underline\>a > a {    text-decoration-line: underline  }  .underline_a a {    text-decoration-line: underline  }  .underline\~a ~ a {    text-decoration-line: underline  }}

子元素選擇器只到第一層

兩棵樹的結構相同。底線標示實際目標連結;縮排與連線分支呈現深度。

文字說明
  1. 帶有 class 的 article 包含連結 A,以及內含連結 B 的 section。
  2. underline>a 只為直接子連結 A 加底線。underline_a 為 A、B 都加底線,因為兩者都是後代連結。
  3. 宣告直接指向這些連結;圖示不是表達從 article 繼承文字裝飾。

同層選擇器從所屬元素向後選取

每排所有節點具有同一個父元素。外框標出的所屬元素帶有 class;底線標示被選取的連結。

文字說明
  1. 同層順序為連結 A、帶有 class 的元素、連結 B、連結 C。
  2. underline+a 選取下一個同層元素 B。underline~a 選取後方的同層連結 B 與 C。
  3. 兩個選擇器都不會選取前方的同層元素 A。若下一個元素不是連結,+a 就不會選取任何元素。

狀態的位置

狀態的位置決定哪個元素必須符合該狀態。這兩個 class 具有相同的父子關係,但在不同位置檢查 hover:

article 上的 classhover 條件加上底線的連結
underline:hover>aarticle 處於 hover所有直接子連結
underline>a:hover直接子連結處於 hover只有該連結

同樣的 hover,不同的目標

兩個範例的第一個連結都處於 hover。藍色虛線輪廓標示符合後綴 :hover 檢查的元素,並非生成的邊框。

文字說明
  1. 兩個 article 都帶有 utility class,並包含相同的兩個直接子連結。第一個連結處於 hover,因此兩個祖先 article 也都符合 :hover。
  2. underline:hover>a 先檢查 article,再選取直接子連結。兩個連結都套用 text-decoration-line: underline。
  3. underline>a:hover 先選取直接子連結,再逐一檢查。只有處於 hover 的第一個連結會套用宣告。
  4. 藍色虛線輪廓標示符合 hover 檢查的元素。它們不代表生成的邊框,也不表示第二個 article 未處於 hover。
<article class="underline:hover>a">  <p>Documentation</p>  <a class="(text-decoration-line:none)" href="/guide/installation">Installation and setup</a>  <a class="(text-decoration-line:none)" href="/reference/packages">API reference</a></article><article class="underline>a:hover">  <p>Documentation</p>  <a class="(text-decoration-line:none)" href="/guide/installation">Installation and setup</a>  <a class="(text-decoration-line:none)" href="/reference/packages">API reference</a></article>
產生的 CSS
@layer utilities {  .\(text-decoration-line\:none\) {    text-decoration-line: none  }  .underline\:hover\>a:hover > a {    text-decoration-line: underline  }  .underline\>a\:hover > a:hover {    text-decoration-line: underline  }}

連結處於 hover 時,其祖先 article 也會處於 hover。第一個範例因此讓兩個連結都符合條件;第二個範例中,另一個連結仍未通過自己的 :hover 檢查。各 class 都屬於 article,但宣告指向它的連結。連結自身的 class 先移除預設底線;權重較高的父子選擇器會在 hover 檢查符合時恢復底線。

選擇器清單

頂層逗號會從同一個帶有 class 的元素開始另一個分支。每個分支都要重複組合器:block>div,>span 會選取直接的 div 子元素與直接的 span 子元素。第二個分支不會接續第一個分支的目標。

<section class="block>div,>span">  <div>First child</div>  <span>Second child</span></section>
產生的 CSS
@layer utilities {  .block\>div\,\>span > div,  .block\>div\,\>span > span {    display: block  }  .\(content\:\'“\'\)\:\:before\,\:\:after::before,  .\(content\:\'“\'\)\:\:before\,\:\:after::after {    content: '“'  }}

函式或引號屬性值中的逗號仍留在該結構內。underline:is(:hover,:focus-visible) 是一個含有兩種選項的選擇器後綴,而非兩個頂層分支。

產生的 CSS
@layer utilities {  .underline\[data-label\=\'draft\,review\'\][data-label='draft,review'] {    text-decoration-line: underline  }  .underline\:is\(\:hover\,\:focus-visible\):is(:hover, :focus-visible) {    text-decoration-line: underline  }}

選擇器清單從 class 所屬元素重新起算

逗號分隔不同選項。每個選擇器都從帶有 class 的元素開始;任一狀態皆可符合。

文字說明
  1. underline:hover,:focus-visible 生成選擇器清單,每個分支都重複完整、跳脫後的 class 所屬元素選擇器。
  2. hover 與 focus-visible 是可擇一的狀態,不要求同時符合。兩條分支共用宣告。

選擇器函式

函式比對行為
:is(...)符合清單中至少一個選擇器
:where(...)與 :is() 相同,但函式及其引數的選擇器權重為零
:not(...)排除符合清單中任一選擇器的元素
:has(...)從目前選取的元素檢查相對關係是否符合

:has() 檢查關係,但不會將宣告移到符合的相關元素。b-blue-60:has(>input:checked) 會在 label 的直接子 input 被勾選時,設定 label 的邊框色彩:

<label class="b(1) b-solid b-line-control b-blue-60:has(>input:checked)"><input type="checkbox" />Include archived items</label>
產生的 CSS
@layer theme {  :root,  :host {    --color-blue-60: oklch(51.83% .2687 266.1)  }}@layer utilities {  .b-blue-60\:has\(\>input\:checked\):has(>input:checked) {    border-color: var(--color-blue-60)  }  .underline\:has\(\+input\:checked\):has(+input:checked) {    text-decoration-line: underline  }}

相對比對也可以是同層元素:underline:has(+input:checked) 會在下一個同層元素是已勾選的 input 時,為帶有 class 的元素加上底線。原生 :has() 限制仍適用;將 :has() 巢狀放在自身內部是無效的。可運作的核取方塊範例與實用備援方式,請見相容性。

has() 檢查子元素,替所屬元素套用樣式

class 位於 label 上。檢查的是 input 的勾選狀態,套用 border-color 的則是 label。

文字說明
  1. b-blue-60:has(>input:checked) 檢查帶有 class 的元素是否具有已勾選的直接子 input。
  2. 符合時,改變的是所屬 label 的邊框色彩,而非 input。input 畫在同一邊界內,以區分檢查位置與樣式目標。

原生狀態

Master CSS 保留原生偽類別名稱。以下列出常用後綴,並非完整的狀態註冊表:

後綴原生比對情境
:hover, :active指標懸停或啟動狀態
:focus, :focus-visible, :focus-within元素取得焦點、顯示焦點指示,或其內部有焦點
:first-child, :last-child, :nth-child(even)同層元素間的位置
:valid, :invalid, :required原生表單限制
:disabled停用的表單控制項
:checked, :indeterminate原生控制項狀態
:dir(rtl), :dir(ltr)解析後的文字方向

請使用 :first-child、:nth-child(odd) 這類完整名稱。即使 Master CSS 能輸出某種拼法,瀏覽器仍可能不支援或視為無效。各狀態的詳細行為以原生偽類別參考為準。

<ul>  <li class="bg-surface-inset:nth-child(even)">Draft</li>  <li class="bg-surface-inset:nth-child(even)">In review</li>  <li class="bg-surface-inset:nth-child(even)">Published</li></ul>
產生的 CSS
@layer theme {  :root,  :host {    --color-zinc-5: oklch(96.5% .0011 265);    --color-zinc-100: oklch(15% .0016 265)  }  :root,  :host {    --color-surface-inset: light-dark(var(--color-zinc-5), var(--color-zinc-100))  }  :root,  :host {    --spacing-xs: .5rem  }}@layer utilities {  .bg-surface-inset\:nth-child\(even\):nth-child(even) {    background-color: var(--color-surface-inset)  }  .mr-xs\:dir\(rtl\):dir(rtl) {    margin-right: var(--spacing-xs)  }  .\(opacity\:\.5\)\:disabled:disabled {    opacity: .5  }}

屬性選擇器

屬性後綴會檢查 DOM 值。布林形式的屬性選擇器檢查屬性是否存在:[open] 比對展開的 details 元素,[data-active] 則在該屬性存在時符合。若要檢查特定狀態值,請包含該值,例如 [aria-pressed=true]。

後綴比對條件
[data-active]屬性存在,即使值為空
[aria-pressed=true]值恰為 true
[href^=https]值以 https 開頭
[href$='.pdf']值以 .pdf 結尾
[title*=master]值包含 master
[lang|=en]值為 en 或以 en- 開頭
[title~=css]以空白分隔的值包含單字 css

屬性值完全相等與單字比對不同

每列以兩個後綴檢查同一個 DOM 屬性值。連字號不構成以空白分隔的單字邊界。

文字說明
  1. [title=css] 只符合恰為 css 的值。[title~=css] 則符合以空白分隔、且等於 css 的單字。
  2. 兩個選擇器都符合 css。只有單字選擇器符合 master css。兩者都不符合 css-in-js。
  3. 選擇器檢查屬性,不會分割 class 字串,也不會編輯屬性值。

引號內的屬性文字保留字面意義:underline[data-state=':first']:first-child 會檢查值 :first,並另外檢查元素位置。[data-id='a_b'] 中的底線留在值內;.is\_active 中跳脫的底線則留在 class 識別名稱內。

<a class="underline[data-state=':first']:first-child" data-state=":first" href="/guide">Guide</a><a class="underline.is\_active is_active" href="/reference">Reference</a>
產生的 CSS
@layer utilities {  .underline\.is\\_active.is\_active {    text-decoration-line: underline  }  .underline\[data-id\=\'a_b\'\][data-id='a_b'] {    text-decoration-line: underline  }  .underline\[data-state\=\'\:first\'\]\:first-child[data-state=':first']:first-child {    text-decoration-line: underline  }}

CSS 引號無法阻止 HTML 空白分隔 class。屬性值中若需要真正的空白,請用 CSS 跳脫,例如 [data-label='New\000020collection']。引號值後可直接接大小寫旗標,例如 [data-kind='draft'i] 代表 ASCII 不分大小寫比對。原生運算子與大小寫比對請見屬性選擇器。

產生的 CSS
@layer utilities {  .underline\[data-kind\=\'draft\'i\][data-kind='draft' i] {    text-decoration-line: underline  }  .underline\[data-label\=\'New\\000020collection\'\][data-label='New\000020collection'] {    text-decoration-line: underline  }}

偽元素

偽元素後綴指向該偽元素,而非產生它的元素。使用生成內容時,請明確撰寫 content 宣告:

<span class="(content:open-quote)::before (content:close-quote)::after">Keep the interface clear.</span>
產生的 CSS
@layer utilities {  .\(background-color\:currentcolor\)\:\:-webkit-scrollbar-thumb::-webkit-scrollbar-thumb {    background-color: currentcolor  }  .\(content\:close-quote\)\:\:after::after {    content: close-quote  }  .\(content\:open-quote\)\:\:before::before {    content: open-quote  }}

生成內容屬於偽元素

引號由真正的 ::before 與 ::after content 宣告生成。三個括弧標示同一個渲染元素的各部分,不代表三個 DOM 子元素。

文字說明
  1. span 內含文字 Keep the interface clear。其 (content:open-quote)::before 與 (content:close-quote)::after class 提供可見的引號。
  2. 每個宣告都指向自己的偽元素。Master CSS 不會建立獨立子元素,也不會只因存在偽元素後綴就加入 content 宣告。

廠商專屬選擇器須明確撰寫。Master CSS 會保留其拼法,不會將偽元素展開成廠商變體,也不會補上瀏覽器支援。引號值中含有括號的情況,請見原生宣告邊界。

選擇器權重

生成的選擇器遵循瀏覽器的選擇器權重規則。無論名稱內有多少標點,跳脫後的 class 名稱都只貢獻一個 class 選擇器的權重。附加的後綴則另外計算。

class, ID-class/屬性/狀態-型別/偽元素CSS
underline0-1-0
underline:hover0-2-0
underline>a0-1-1
underline:where(:hover,#selected)0-1-0
underline:is(:hover,#selected)1-1-0

:is()、:not() 與 :has() 採用其選擇器清單中最高的權重。:where() 不增加權重,包含其引數也是如此。組合器與通用選擇器也不增加權重。這些權重是在階層串接已決定來源、重要性與串接層優先順序後才適用;較高權重的選擇器不會自動勝過另一個串接層中的規則。

產生的 CSS
@layer utilities {  .underline\:is\(\:hover\,\#selected\):is(:hover, #selected) {    text-decoration-line: underline  }  .underline\:where\(\:hover\,\#selected\):where(:hover, #selected) {    text-decoration-line: underline  }}

where() 與 is() 可比對相同狀態,但權重不同

圖示只比較選擇器權重。階層串接會先考量來源、重要性與串接層優先順序。

文字說明
  1. 兩個生成選擇器中,跳脫後的完整 class 所屬元素都貢獻 0-1-0。
  2. :where(:hover,#selected) 的後綴貢獻 0-0-0,因此總計為 0-1-0。
  3. 對 :is(:hover,#selected) 而言,ID 引數提供最高引數權重 1-0-0,所以即使符合的是 hover 選項,總計仍為 1-1-0。

規則排序請見串接層,實務決策請見 指南的覆寫流程。重新排列 HTML class 不會改變選擇器權重。

外部情境

後綴以帶有 class 的元素為起點。目標需要依祖先或前方同層元素套用樣式時,可以用原生 CSS 規則直接表達關係:

@layer components {  .active .contextual {    display: none;  }  .active > .child-contextual {    display: none;  }  .active + .adjacent-contextual {    display: none;  }  .active ~ .sibling-contextual {    display: none;  }}

若要將數個 utility 宣告包在相同關係中,請用含有原生選擇器與 @contents 的 mixin。mixin 內容契約定義展開與轉送方式;重複使用樣式說明何時適合選用此形式。

生成 CSS 證明已輸出規則,不代表瀏覽器一定支援或符合該選擇器。請檢查 DOM 關係、實際狀態與原生選擇器合法性。在一般 CSS 選擇器清單中,無效分支可能使整份清單失效;:is() 與 :where() 則使用容錯清單。瀏覽器檢查與備援設計請見相容性。