CSS Podcast - 015: 擬似類別
假設您有一個電子郵件註冊表單,且希望電子郵件表單欄位在包含無效電子郵件地址時顯示紅色邊框。該如何進行?您可以使用 :invalid
CSS 擬類別,這是瀏覽器提供的眾多擬類別之一。
您可以使用擬造類別,根據狀態變更和外部因素套用樣式。也就是說,您的設計可以回應使用者輸入的內容,例如無效的電子郵件地址。這些內容會在「選取器」單元中介紹,您可以進一步瞭解這些選取器。
與前一個單元中的偽元素不同,偽類別會連結至元素可能處於的特定狀態,而非該元素的一般樣式部分。
互動式狀態
下列擬似類別會在使用者與網頁互動時套用。
:hover
如果使用者有滑鼠或觸控板等指標裝置,並將其放在元素上,您可以使用 :hover
鉤住該狀態,以套用樣式。這是一種有用的提示方式,可讓使用者知道可與元素互動。
:active
當使用者積極與元素互動 (例如點擊) 時,系統會在點擊釋放前觸發這個狀態。如果使用滑鼠等指標裝置,則此狀態是指點擊開始時,且尚未釋放。
:focus
、:focus-within
和:focus-visible
如果元素可接收焦點 (例如 <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
:target
擬似類別會選取具有與網址片段相符的 id
元素。假設您有以下 HTML:
<article id="content">
…
</article>
如果網址包含 #content
,您可以將樣式附加至該元素。
#content:target {
background: yellow;
}
這項功能可用於醒目顯示可能已透過跳躍連結連結到的區域,例如網站的主要內容。
歷史狀態
:link
:link
擬似類別可套用至任何 <a>
元素,只要該元素含有尚未造訪的 href
值。
:visited
您可以使用 :visited
擬造類別,為使用者已造訪的連結套用樣式。這是 :link
的反向狀態,但您可用的 CSS 屬性較少,原因是安全性。您只能為 color
、background-color
、border-color
、outline-color
和 SVG fill
和 stroke
的顏色設定樣式。
順序很重要
如果您定義 :visited
樣式,則可由至少具有相同特異性的連結虛擬類別覆寫。因此,建議您使用 LVHA 規則,以特定順序為含有擬造類別的連結設定樣式::link
、:visited
、:hover
、:active
。
a:link {}
a:visited {}
a:hover {}
a:active {}
表單狀態
下列擬似類別可選取表單元素,並在這些元素與使用者互動時,顯示這些元素的各種狀態。
:disabled
和:enabled
如果瀏覽器停用表單元素 (例如 <button>
),您可以使用 :disabled
疑似類別鉤掛該狀態。:enabled
擬似類別可用於相反的狀態,但表單元素預設為 :enabled
,因此您可能不會使用這個擬似類別。
:checked
和:indeterminate
當支援的表單元素 (例如核取方塊或圓形按鈕) 處於勾選狀態時,即可使用 :checked
擬造類別。
:checked
狀態是二進位(true 或 false) 狀態,但核取方塊在未勾選或取消勾選時,確實有介於兩者之間的狀態。這就是所謂的 :indeterminate
狀態。
舉例來說,如果您有「選取全部」控制項,會勾選群組中的所有核取方塊,就會出現這種狀態。如果使用者隨後取消勾選其中一個核取方塊,根核取方塊就不會再代表勾選「全部」,因此應置於未定狀態。
<progress>
元素也有可設定樣式的不確定狀態。常見的用途是將其顯示為條紋狀,以表示目前無法確定需要多少。
:placeholder-shown
如果表單欄位具有 placeholder
屬性和沒有值,您可以使用 :placeholder-shown
擬造類別,將樣式套用至該狀態。只要欄位中含有內容 (無論是否含有 placeholder
),系統就不會再套用此狀態。
驗證狀態
您可以使用疑似類別回應 HTML 表單驗證,例如 :valid
、:invalid
和 :in-range
。:valid
和 :invalid
擬似類別適用於電子郵件欄位等情境,因為這些欄位含有需要比對的 pattern
,才能成為有效欄位。您可以向使用者顯示這個有效值狀態,協助他們瞭解可以安全地移至下一個欄位。
如果輸入內容含有 min
和 max
(例如數值輸入內容),:in-range
擬類別就會可用,且值會在這些範圍內。
在 HTML 表單中,您可以使用 required
屬性判斷欄位是否為必填欄位。:required
擬似類別可用於必填欄位。您可以使用 :optional
擬似類別選取非必要欄位。
依索引、順序和出現次數選取元素
有一系列的擬似類別,可根據項目在文件中的所在位置選取項目。
:first-child
和:last-child
如要找出第一或最後一個項目,可以使用 :first-child
和 :last-child
。這些擬似類別會傳回一組同層元素中的第一個或最後一個元素。
:only-child
您也可以使用 :only-child
擬造類別,選取沒有同層元素的元素。
:first-of-type
和:last-of-type
您可以選取 :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
您也不必侷限於第一個和最後一個子項和類型。:nth-child
和 :nth-of-type
虛擬類別可讓您指定特定索引的元素。CSS 選取器中的索引從 1 開始。
您也可以將索引以外的值傳遞至這些擬類別。如要選取所有偶數元素,可以使用 :nth-child(even)
。
您也可以使用 An+B 微語法,建立更複雜的選取器,以便在固定間隔找到項目。
li:nth-child(3n+3) {
background: yellow;
}
這個選取器會從第 3 個項目開始,選取每隔一個項目。這個運算式中的 n
是從 0 開始的索引,而 3 (3n
) 則是該索引的乘數。
假設您有 7 個 <li>
項目。系統會選取 3 這個項目,因為 3n+3
會轉譯為 (3 * 0) + 3
。下一個疊代作業會選取項目 6,因為 n
現已遞增至 1
,因此為 (3 * 1) + 3)
。這個運算式適用於 :nth-child
和 :nth-of-type
。
您可以使用這個第 n 個子項測試器或這個數量選取器工具,試驗這類選取器。
:only-of-type
最後,您可以使用 :only-of-type
在同層元素中找出某種類型元素。如果你想選取只有一個項目的清單,或是想找出段落中唯一的粗體元素,這項功能就非常實用。
尋找空白元素
有時您可能需要辨識完全空白的元素,這時也可以使用偽類別。
:empty
如果元素沒有子項,則會套用 :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()
如果您想在 .post
元素中尋找所有 h2
、li
和 img
子元素,建議您編寫類似以下的選擇器清單:
.post h2,
.post li,
.post img {
…
}
您可以使用 :is()
擬類別,編寫更精簡的版本:
.post :is(h2, li, img) {
…
}
:is
擬群組別不僅比選取器清單更精簡,也更寬容。在大多數情況下,如果選取器清單中出現錯誤或不支援的選取器,整個選取器清單就會停止運作。如果 :is
擬類別中傳遞的選取器發生錯誤,系統會忽略無效的選取器,但會使用有效的選取器。
:not()
您也可以使用 :not()
擬類別排除項目。舉例來說,您可以使用它為所有沒有 class
屬性的連結套用樣式。
a:not([class]) {
color: blue;
}
:not
擬類別也可以協助您改善無障礙存取功能。舉例來說,<img>
必須有 alt
,即使是空值也一樣,因此您可以編寫 CSS 規則,為無效圖片加上粗紅色輪廓:
img:not([alt]) {
outline: 10px red;
}
進行隨堂測驗
測驗您對擬類別的瞭解
虛擬類別會以類別已動態套用至元素的方式運作,而虛擬元素則會對元素本身運作。
以下何者為功能性擬類別?
:is()
:not()
:empty
:target
下列哪個疑似類別是由於使用者互動而產生?
:hover
:target
:press
:focus-within
:squeeze
下列何者為 <form>
狀態的擬造類別?
:enabled
:valid
:indeterminate
:in-range
:fresh
:loading
:checked