虛擬類別

CSS Podcast - 015: Pseudo-classes

假設您收到電子郵件註冊表單,且希望電子郵件表單欄位包含無效的電子郵件地址時加上紅色邊框。該怎麼做? 您可以使用 :invalid CSS 虛擬類別,這是瀏覽器提供的許多虛擬類別之一。

虛擬類別可讓您根據狀態變更和外部因素套用樣式。也就是說,您的設計可以回應使用者輸入內容,例如無效的電子郵件地址。選取器模組會說明這些內容,本單元將詳細說明。

您可以在上一個模組中進一步瞭解虛擬元素,而虛擬元素會掛接至特定元素可能所在的特定狀態,而非該元素的一般樣式。

互動狀態

由於使用者與網頁互動,系統套用了下列虛擬類別。

:hover

瀏覽器支援

  • 1
  • 12
  • 1
  • 2

資料來源

如果使用者擁有滑鼠或觸控板等指標裝置,並放置在元素上方,您可以使用 :hover 掛載至該狀態,藉此套用樣式。這個方法非常實用,可以提示元素能進行互動。

:active

瀏覽器支援

  • 1
  • 12
  • 1
  • 1

資料來源

在點擊發生前,元素主動互動 (例如點擊),就會觸發這個狀態。如果使用滑鼠這類指標裝置,這個狀態就是點擊開始且尚未釋放。

:focus:focus-within:focus-visible

瀏覽器支援

  • 1
  • 12
  • 1
  • 1

資料來源

如果元素可以接收焦點 (例如 <button>),您可以使用 :focus 虛擬類別回應該狀態。

您也可以使用 :focus-within 回應元素的子元素是否收到焦點。

當焦點位在可聚焦的元素上 (點選按鈕) 時,聚焦元素仍會顯示對焦環。在這類情況下,開發人員將採用下列 CSS:

button:focus {
    outline: none;
}

當元素收到焦點時,CSS 會移除預設的瀏覽器焦點環,對使用鍵盤瀏覽網頁的使用者造成無障礙功能問題。如果沒有聚焦樣式,就無法使用 Tab 鍵追蹤焦點目前所在的位置。透過 :focus-visible,當元素透過鍵盤收到焦點時,您就可以顯示焦點樣式,同時使用 outline: none 規則防止焦點裝置在指標裝置與其互動時出現。

button:focus {
    outline: none;
}

button:focus-visible {
    outline: 1px solid black;
}

:target

瀏覽器支援

  • 1
  • 12
  • 1
  • 1.3

資料來源

:target 虛擬類別會選取具備 id 與網址片段相符的元素。假設您擁有下列 HTML:

<article id="content">
    …
</article>

當網址包含 #content 時,您可以將樣式附加至該元素。

#content:target {
    background: yellow;
}

這對於醒目顯示可能透過略過連結明確連結的區域 (例如網站上的主要內容) 很有幫助。

歷史狀態

瀏覽器支援

  • 1
  • 12
  • 1
  • 1

資料來源

如果 <a> 元素包含「尚未」造訪 href 值,則 :link 虛擬類別可套用於任何 <a> 元素。

:visited

您可以使用 :visited 虛擬類別,設定使用者已造訪連結的樣式。這與 :link 相反,但基於安全性考量,您可用的 CSS 屬性較少。您只能設定 colorbackground-colorborder-coloroutline-color 樣式,以及 SVG fillstroke 的顏色。

訂單案件

如果您定義了 :visited 樣式,則可由至少具有明確性的連結虛擬類別覆寫。因此,建議您套用 LVHA 規則來設定包含虛擬類別的連結,並依照特定順序排列::link:visited:hover:active

a:link {}
a:visited {}
a:hover {}
a:active {}

表單狀態

下列虛擬類別可以選取表單元素,前提是這些元素可能在互動期間可能處於多種狀態。

:disabled:enabled

瀏覽器支援

  • 1
  • 12
  • 1
  • 3.1

資料來源

如果瀏覽器停用 <button> 等表單元素,您可以使用 :disabled 虛擬類別連接到該狀態。:enabled 虛擬類別適用於相反狀態,但表單元素預設為 :enabled,因此您可能無法發現自己達到這個虛擬類別。

:checked:indeterminate

瀏覽器支援

  • 1
  • 12
  • 1
  • 3.1

資料來源

如果支援的表單元素 (例如核取方塊或圓形按鈕) 處於已勾選狀態,即可使用 :checked 虛擬類別。

:checked 狀態是二進位(true 或 false) 狀態,但如果核取方塊不處於勾選或未勾選狀態,核取方塊的狀態會是進項。這就是 :indeterminate 狀態。

舉例來說,如果您使用「全選」控制項來勾選群組中所有核取方塊,便屬於這種狀態。 如果使用者隨後取消勾選其中一個核取方塊,根核取方塊將不再代表已勾選「全部」,因此應進入不確定狀態。

<progress> 元素同樣具有可設定樣式的不確定狀態。其中一種常見用途是提供條紋外觀,讓使用者知道需要更多項目。

:placeholder-shown

瀏覽器支援

  • 47
  • 79
  • 51
  • 9

資料來源

如果表單欄位包含 placeholder 屬性且沒有任何值,您可以使用 :placeholder-shown 虛擬類別將樣式附加到該狀態。一旦欄位中有內容 (無論是否有 placeholder),就不再套用這個狀態。

驗證狀態

瀏覽器支援

  • 10
  • 12
  • 4
  • 5

資料來源

您可以使用虛擬類別 (例如 :valid:invalid:in-range) 回應 HTML 表單驗證。:valid:invalid 虛擬類別對於成為有效欄位等情況非常有用,例如電子郵件欄位包含需比對的 pattern。系統會向使用者顯示這個有效值狀態,協助他們瞭解可以安全地移至下一個欄位。

如果輸入包含 minmax (例如數字輸入「且」值在邊界內),即可使用 :in-range 虛擬類別。

使用 HTML 表單時,您可以透過 required 屬性判斷是否為必要欄位。必填欄位將可使用 :required 虛擬類別。使用 :optional 虛擬類別可以選取不需要的欄位。

按照元素的索引、順序和出現次數選取元素

系統會產生一組虛擬類別,根據項目在文件中的位置選取項目。

:first-child:last-child

瀏覽器支援

  • 4
  • 12
  • 3
  • 3.1

資料來源

如要尋找第一個或最後一個項目,可以使用 :first-child:last-child。這些虛擬類別會傳回同層元素群組中第一個或最後一個元素。

:only-child

瀏覽器支援

  • 2
  • 12
  • 1.5
  • 3.1

資料來源

您也可以使用 :only-child 虛擬類別選取沒有同層級的元素。

:first-of-type:last-of-type

瀏覽器支援

  • 1
  • 12
  • 3.5
  • 3.1

資料來源

您可以先選取 :first-of-type:last-of-type,其運作方式與 :first-child:last-child 相同,但請考慮使用以下 HTML:

<div class="my-parent">
    <p>A paragraph</p>
    <div>A div</div>
    <div>Another div</div>
</div>

以下 CSS:

.my-parent div:first-child {
    color: red;
}

由於第一個子項是段落,而不是 div,因此沒有任何元素的顏色是紅色。在這種情況下,:first-of-type 虛擬類別非常實用。

.my-parent div:first-of-type {
    color: red;
}

即使第一個 <div> 是第二個子項,仍是 .my-parent 元素中的第一個類型,因此這項規則會以紅色標示。

:nth-child:nth-of-type

瀏覽器支援

  • 1
  • 12
  • 3.5
  • 3.1

資料來源

您不限於第一個和最後一個子項,且不限類型。:nth-child:nth-of-type 虛擬類別可讓您指定位於特定索引的元素。CSS 選取器中的索引從 1 開始。

您可以將多個索引傳遞至這些虛擬類別。如要選取所有元素,可以使用 :nth-child(even)

您也可以使用 An+B 微語法建立更複雜的選取器,以定期間隔尋找項目。

li:nth-child(3n+3) {
    background: yellow;
}

這個選取器會選取所有第三個項目,從項目 3 開始。這個運算式中的 n 是索引,從 3 開始 (3n) 是將索引乘以多少。

假設您有 7 個 <li> 項目,因為 3n+3 會轉譯為 (3 * 0) + 3,所以選取的第一個項目為 3。下一個疊代會選擇項目 6,因為 n 現已遞增至 1,因此 (3 * 1) + 3)。這個運算式適用於 :nth-child:nth-of-type

您可以使用這個第 n 位子測試人員或這項數量選取器工具來嘗試這種選取器。

:only-of-type

瀏覽器支援

  • 1
  • 12
  • 3.5
  • 3.1

資料來源

最後,您可以在使用 :only-of-type 的同層級群組中找到特定類型的元素。如果您想選取只有一個項目的清單,或者想找出段落中唯一的粗體元素,這個方法就非常實用。

尋找空白元素

有時有助於找出完全空白的元素,而您也可以透過虛擬類別進行確認。

:empty

瀏覽器支援

  • 1
  • 12
  • 1
  • 3.1

資料來源

如果元素沒有子項,就會套用 :empty 虛擬類別。然而,子項不僅是 HTML 元素或文字節點,也可能是空白字元,當您對下列 HTML 進行偵錯時,可能會疑惑為什麼無法與 :empty 搭配運作:

<div>
</div>

原因是開頭和結尾 <div> 之間留有空白字元,因此空白功能無法運作。

如果您無法控管 HTML,而且想要隱藏空白元素 (例如 WYSIWYG 內容編輯器),:empty 虛擬類別就非常實用。這裡的編輯器加入了一個雜亂的空白段落。

<article class="post">
 <p>Donec ullamcorper nulla non metus auctor fringilla.</p>
 <p></p>
 <p>Curabitur blandit tempus porttitor.</p>
</article>

你可以使用 :empty 找出並隱藏。

.post :empty {
    display: none;
}

尋找和排除多個元素

有些虛擬類別可協助您編寫更精簡的 CSS。

:is()

瀏覽器支援

  • 88
  • 88
  • 78
  • 14

資料來源

如果您想找出 .post 元素中的所有 h2liimg 子項元素,您可以考慮編寫如下的選取器清單:

.post h2,
.post li,
.post img {
    …
}

使用 :is() 虛擬類別,您可以編寫更精簡的版本:

.post :is(h2, li, img) {
    …
}

:is 虛擬類別不僅比選取器清單更精簡,也更複雜。在大多數情況下,如果選取器清單中出現錯誤或不支援的選取器,整個選取器清單就會停止運作。如果 :is 虛擬類別中傳遞的選取器發生錯誤,系統會忽略無效的選取器,但使用有效的選取器。

:not()

瀏覽器支援

  • 1
  • 12
  • 1
  • 3.1

資料來源

您可以使用 :not() 虛擬類別排除項目。舉例來說,您可以使用該參數來設定所有沒有 class 屬性的連結樣式。

a:not([class]) {
    color: blue;
}

:not 虛擬類別也有助於改善無障礙功能。舉例來說,<img> 必須有 alt (即使值是空白值),所以您可以撰寫 CSS 規則,為無效圖片加入粗細的紅色外框:

img:not([alt]) {
    outline: 10px red;
}

隨堂測驗

測驗您對虛擬類別的相關知識

虛擬類別的行為就像是將類別動態套用至元素一樣,虛擬元素則會依元素本身執行。

留意如何在選取器中使用單一或多個 : 做為按鍵識別字元
false
虛擬元素適用於零件,虛擬類別適用於狀態。

下列何者屬於「功能」虛擬類別?

:is()
🎉
:target
函式虛擬類別後面有 (),表示其接受參數。
:empty
函式虛擬類別後面有 (),表示其接受參數。
:not()
🎉

哪些虛擬類別是由使用者互動所產生?

:hover
🎉
:press
請再試一次!
:squeeze
請再試一次!
:target
🎉
:focus-within
🎉

以下何者是 <form> 狀態虛擬類別?

:enabled
🎉
:fresh
請再試一次!
:indeterminate
🎉
:checked
🎉
:in-range
🎉
:loading
請再試一次!
:valid
🎉