
昨天我們學會了如何使用基本與組合選擇器來精準選取 HTML 標籤。但網頁不只是靜態的文字與區塊,使用者還會滑過按鈕、點擊輸入框,甚至我們有時只想裝飾某個段落的第一個字、或是憑空加個小圖示,這時候該怎麼做呢?
這個時候,就輪到 「偽類」 與 「偽元素」 登場了!話不多說,我們馬上來看看怎麼使用吧!(ノ>ω<)ノ
偽類是一種特殊選擇器,通常以「一個冒號(:)」作為開頭,並搭配其他選擇器使用,能夠選取處於「特定狀態」或「特定位置」的元素。例如,元素是否接觸到游標,或是否被勾選等動態情況,屬於元素的特定狀態;而明確指定選取第一個、最後一個子元素等結構位置,則是針對元素的特定位置進行選取。
動態偽類(Dynamic Pseudo-classes)
根據元素與使用者互動時的「動態狀態」來選取元素,例如:游標滑入按鈕、點擊表單等情況。


使用範例:
a:hover { color: red; } /* 游標滑入懸停 */
a:active { color: orange; } /* 點擊時 */
input:focus { border-color: blue; } /* 獲得焦點 */
input:blur { border-color: gray; } /* 失去焦點 */
a:link { color: blue; } /* 未點擊的連結 */
a:visited { color: purple; } /* 已點擊的連結 */
範例:一個藍色的按鈕,滑鼠 hover、focus、active 分別會有不同的效果。
.btn {
padding: 12px 20px;
font-size: 16px;
color: #ffffff;
background-color: #3b82f6; /* 預設為藍色 */
border: none;
border-radius: 8px;
cursor: pointer; /* 游標變成手指 */
transition: 0.2s; /* 過度動畫 */
}
/* 1. 滑鼠懸停 (Hover) */
.btn:hover {
background-color: #2563eb; /* 背景顏色變深藍色 */
}
/* 2. 鍵盤聚焦/選取 (Focus) */
.btn:focus {
outline: 3px solid #3b82f666; /* 半透明藍色外框 */
}
/* 3. 滑鼠按住/點擊中 (Active) */
.btn:active {
background-color: #1641ba; /* 背景顏色變更深的藍色 */
}
<button class="btn">點擊我</button>

結構偽類(Structural Pseudo-classes)
根據元素在 HTML 文件結構中的「位置與順序」來選取元素。
常用於裝飾清單或表格,等元素內部有多個項目的情況。可能需要為首尾項目套用不同樣式,或是每一行需設定交替顏色等使用情況。


使用範例:
:first-child { font-weight: bold; } /* 第一個子元素 */
:last-child { margin-bottom: 0; } /* 最後一個子元素 */
:only-child { text-align: center; } /* 唯一子元素 */
/* nth-child 計算所有子元素 */
li:nth-child(2) { color: red; } /* 第 2 個子元素 */
li:nth-child(odd) { background: #f0f0f0; } /* 奇數子元素 */
li:nth-child(even) { background: white; } /* 偶數子元素 */
li:nth-child(3n) { font-weight: bold; } /* 每 3 個 */
li:nth-child(3n+1) { color: blue; } /* 3n+1 位置 */
/* nth-of-type 只計算同類型元素 */
p:nth-of-type(2) { margin-top: 2em; } /* 第 2 個 p 元素 */
img:nth-of-type(odd) { float: left; } /* 奇數位置的圖片 */
/* 反向數值選擇 */
li:nth-last-child(2) { color: orange; } /* 倒數第 2 個子元素 */
p:nth-last-of-type(1) { font-style: italic; } /* 倒數第 1 個 p */
例如:選取容器裡面的,第一個或是最後一個元素,需要使用特別的圓角。或是選取容器裡面的,偶數行要使用不同的背景顏色。
.item {
padding: 12px 16px;
background-color: #ffffff;
}
/* 偶數行使用不同背景顏色 */
.item:nth-child(even) {
background-color: #f2f2f2;
}
/* 第一個元素:上方圓角 */
.item:first-child {
border-top-left-radius: 8px;
border-top-right-radius: 8px;
}
/* 最後一個元素:下方圓角 */
.item:last-child {
border-bottom-left-radius: 8px;
border-bottom-right-radius: 8px;
}
<div class="container">
<div class="item">項目 1 (第一個元素:上方圓角)</div>
<div class="item">項目 2 (偶數行:不同背景)</div>
<div class="item">項目 3 (奇數行)</div>
<div class="item">項目 4 (偶數行:不同背景)</div>
<div class="item">項目 5 (最後一個元素:下方圓角)</div>
</div>

表單相關偽類(Form Pseudo-classes)
針對表單元素(如 <input>、<select>、<textarea>、<button>)的「特定狀態」選取元素。例如:可以選取 <input type="text" disabled> 正在禁用的文字輸入欄位。


使用範例:
input:disabled { opacity: 0.5; } /* 禁用狀態 */
input:enabled { cursor: pointer; } /* 啟用狀態 */
input:checked { background: green; } /* 勾選狀態 */
功能性偽類(Functional Pseudo-classes)
在選取元素時附加額外的「條件篩選」功能,用來進一步限定選取範圍。

p:not(.special) { color: gray; } /* 不是 .special 的 p */
input:not([type="hidden"]) { display: block; } /* 不是隱藏的 input */
li:not(:first-child) { margin-top: 10px; } /* 不是第一個的 li */
.card:has(img) {...} /* 選取裡面有圖片的卡片 */
.card:not(:has(img)) {...} /* 選取裡面沒有圖片的卡片 */
範例 1:想選 p 但是想要排除有使用 .special 的 class 的元素,所以以下範例「文字 2」就會被排除掉,不會被選上。
p:not(.special) {
color: red;
}
<p class="text">文字 1(會被選中)</p>
<p class="text special">文字 2(不會被選中)</p>
<p class="text">文字 3(會被選中)</p>
範例 2:想要選裡面有 span 的 p 元素,因為被選上的 p 裡面有一個 span 文字 2,所以會選到包文字 2 的 p 元素。
p:has(span) {
color: red;
}
<p class="text">文字 1(不會被選中)</p>
<p class="text">(會被選中)
<span>文字 2</span>
</p>
<p class="text">文字 3(不會被選中)</p>
偽元素是 CSS 提供的虛擬元素,以「兩個冒號(::)」開頭,並與其他選擇器搭配使用。能在不修改 HTML的情況下插入內容,是一個「無實體標籤的虛擬元素」。
例如,要在標題前加裝飾方塊或文字,可能會需要在 HTML 中額外加新的 或其他標籤;而使用偽元素則可以直接在 CSS 中完成,無需修改 HTML 結構。
before 與 after
::before - 位於元素之前的內容。
::after - 位於元素之後的內容。

兩個偽元素預設為隱藏,需要設定 content 屬性才能顯示,可以設定要插入的字串或空字串。
顯示後可像一般 HTML 元素設定各種 CSS 樣式。
具有內容區域的標籤,也就是有開始與結束標籤的元素,如 <div></div>、<p></p> 等,支援這兩個偽元素。不具內容區域的標籤,也就是自閉合標籤,如:<img>、<input>等則不支援。
範例 1:將文字寫在 .quote 元素裡面,前面後面就會自動加上「上引號」跟「下引號」!
.quote::before { content: "「"; } /* 元素前插入內容 */
.quote::after { content: "」"; } /* 元素後插入內容 */
範例 2:幫文字前面做一個裝飾方塊!
h2.title {
font-size: 20px;
padding: 8px;
display: flex;
align-items: center; /* 垂直置中 */
gap: 8px;
&::before {
content: ""; /* 要使用就需要寫 */
background: #999;
width: 4px;
height: 1em; /* 父元素字體大小 */
border-radius: 8px;
}
}
<h2 class='title'>標題</h2>

其他偽元素
::first-line - 選取元素第一行文字
::first-letter - 選取元素第一個字母
::placeholder - 設定輸入框提示文字樣式
::selection - 控制選取文字時樣式
/* 文字偽元素 */
p::first-line { font-weight: bold; } /* 第一行文字 */
p::first-letter { font-size: 2em; } /* 第一個字母 */
::selection { background: yellow; } /* 選取的文字 */
/* 表單偽元素 */
input::placeholder { color: #999; } /* 佔位符文字 */

今天我們介紹了比較進階的選擇器「偽類」與「偽元素」:
:hover、:focus)、結構排版(:nth-child、:first-child)以及強大的條件篩選(:not、:has),讓樣式隨狀態靈活變化。::before 與 ::after(別忘了要設定 content!),不必增加多餘的 HTML 標籤就能做出引號、裝飾線或小圖標,乾淨又優雅。學到這裡,你手上已經有滿滿的選擇器工具了!但當多個選擇器同時選中同一個元素、樣式打架時,瀏覽器到底會聽誰的?明天我們將深入探討 CSS 中最關鍵的「選擇器優先權(權重)」,教你如何看懂權重、避免樣式被意外覆蓋,敬請期待囉!(ゝ∀・)
