虛擬類別選擇器 ( 結構位置 )
虛擬類別選擇器是根據「元素的狀態」來選取元素,這篇教學會介紹透過元素在「文件結構」中的「位置」狀態,進行選取元素的虛擬類別選擇器,這類型的選擇器有 :root、empty、:first-child、:last-child、:nth-child(n)、:nth-last-child(n) 和 :only-child,都是非常方便實用的選擇器。
「結構位置」虛擬類別選擇器
下方列出和「結構位置」有關的虛擬類別選擇器 ( 支援度 All 表示主流瀏覽器都支援 ):
虛擬類別選擇器 | 說明 | 支援度 |
---|---|---|
:root | 文件根元素,如果是 html 文件就是 html 元素。 | All |
:empty | 元素裡沒有任何元素、字元或換行。 | All |
:first-child | 同一層元素裡的第一個元素。 | All |
:last-child | 同一層元素裡的最後一個元素 | All |
:nth-child(n) | 同一層元素裡,從頭數來第 n 個元素。 | All |
:nth-last-child(n) | 同一層元素裡,倒數第 n 個元素。 | All |
:only-child | 同一層只有自己一個元素。 | All |
:root
「:root
」表示文件的「根元素」,在網頁 HTML 文件裡通常指的是「html
」元素,但由於網頁有時並非完全由 HTML 構成,有些時候會使用 XML 或 RSS,對應的根元素就會不相同,下方的 CSS 會讓 html 元素的背景變成灰色。
:root {background: gray;}
:empty
「:empty
」表示「空元素」,泛指「元素裡沒有任何元素、字元或換行」,有時透過程式自動產生的網頁,或一些特殊需求的網頁,會多出一些沒有任何內容的元素,透過 :empty
選取這些元素後,搭配「display: none;
」的樣式,就能隱藏這些不應該存在的空元素,如此一來就不用特別透過 JavaScript 來清除這些元素。
:empty {display: none;}
除了隱藏空元素的功能,也可以透過樣式的設定,替空元素加上特殊樣式,例如下方的 CSS 會將所有的空元素加上灰色背景,但如果是「空的 div 元素」,就會變成紅色背景。
<!-- HTML 程式碼 -->
<h2></h2>
<h3></h3>
<div></div>
<!-- CSS 程式碼 -->
<style>
* {width: 100px; height: 50px;} /* 所有元素的寬 100px 高 50px */
:empty {background: gray;} /* 所有空元素的背景灰色 */
div:empty {background: red;} /* 所有空元素是 div,背景紅色 */
</style>
:first-child
「:first-child
」表示「同一層裡的第一個元素」,下方的 CSS 會將 body 裡,所有元素中的第一個子元素都變成紅色文字,注意,如果直接寫「* :first-child
」,會造成 body 裡的第一個元素也會變成紅色。
<!-- HTML 程式碼 -->
<ul>
<li>apple</li> <!-- ul 裡第一個子元素 -->
<li>orange</li>
<li>banana</li>
</ul>
<div>
<h2>oxxo.studio</h2> <!-- div 裡的第一個子元素 -->
<h3>hello world!!</h3>
<span><em>Yes</em> or <em>No</em></span> <!-- 第一個 em 為 span 裡第一個子元素 -->
</div>
<!-- CSS 程式碼 -->
<style>
body * :first-child {color: red;} /* body 裡所有元素中的第一個子元素呈現紅色文字 */
</style>
除了單除使用 :first-child
,如果在「開頭加上元素名稱」,就會表示「指定的元素的第一個」,以下方的 CSS 為例,就會單獨將第一個 li 變色,而不會影響到其他的元素。
body * li:first-child {color: red;} /* body 裡所有元素中的第一個 li 呈現紅色文字 */
如果在「沒有指定元素名稱」的狀況下使用 :first-child
,需要注意瀏覽器在渲染網頁時,會自動添加一些「隱藏元素」,例如 table 元素就有隱藏了一個 tbody 元素,如果單純使用 table *:first-child
,會發生內容元素全部套用樣式的狀況,因為 table 的第一個子元素是隱藏的 tbody,如果要解決這個問題,就需要明確定義元素名稱。
<!-- HTML 程式碼 -->
<table border="1">
<tr>
<td>AAA</td><td>BBB</td>
</tr>
<tr>
<td>CCC</td><td>DDD</td>
</tr>
</table>
<!-- CSS 程式碼 -->
<style>
table :first-child {color: red;}
</style>
:last-child
「:last-child
」表示「同一層裡的最後一個元素」,下方的 CSS 會將 body 裡,所有元素中的最後的子元素都變成紅色文字,注意,如果直接寫「* :last-child
」,會造成 body 裡的最後一個元素也會變成紅色。
<!-- HTML 程式碼 -->
<ul>
<li>apple</li>
<li>orange</li>
<li>banana</li> <!-- ul 裡最後一個子元素 -->
</ul>
<div>
<h2>oxxo.studio</h2>
<h3>hello world!!</h3>
<span><em>Yes</em> or <em>No</em></span> <!-- div 裡的最後一個子元素 -->
</div>
<!-- CSS 程式碼 -->
<style>
body * :last-child {color: red;} /* body 裡所有元素中的最後一個子元素呈現紅色文字 */
</style>
除了單除使用 :last-child
,如果在「開頭加上元素名稱」,就會表示「指定的元素的最後一個」,以下方的 CSS 為例,就會單獨將最後一個 li 變色,而不會影響到其他的元素。
body * li:last-child {color: red;} /* body 裡所有元素中的最後一個 li 呈現紅色文字 */
:nth-child(n)
「:nth-child(n)
」表示「同一層元素裡,從頭數來第 n 個元素」,下方的 CSS 會將 body 裡,所有元素中從頭數來的第二個子元素都變成紅色文字。
<!-- HTML 程式碼 -->
<ul>
<li>apple</li>
<li>orange</li> <!-- ul 裡第二個子元素 -->
<li>banana</li>
<li>grape</li>
</ul>
<div>
<h2>oxxo.studio</h2>
<h3>hello world!!</h3> <!-- div 裡的第二個子元素 -->
<span><em>Yes</em> or <em>No</em></span> <!-- No 是 span 裡第二個子元素 -->
<a>Google</a>
</div>
<!-- CSS 程式碼 -->
<style>
body * :nth-child(2) {color: red;} /* body 裡所有元素中從頭數來的第二個子元素呈現紅色文字 */
</style>
除了單除使用 :nth-child(n)
,如果在「開頭加上元素名稱」,就會表示「指定的元素的第二個」,以下方的 CSS 為例,就會單獨將第二個 li 變色,而不會影響到其他的元素。
body * li:nth-child(2) {color: red;} /* body 裡所有元素中的第二個 li 呈現紅色文字 */
:nth-child(n)
裡的 n 不僅可以只是數字,也可以使用奇數「odd」和偶數「even」這兩個英文單字,使用後就會自動取得奇數項元素或偶數項元素。
<!-- HTML 程式碼 -->
<ul>
<li>apple</li>
<li>orange</li> <!-- 偶數變色 -->
<li>banana</li>
<li>grape</li> <!-- 偶數變色 -->
<li>papaya</li>
<li>coconut</li> <!-- 偶數變色 -->
</ul>
<ol>
<li>apple</li> <!-- 奇數變色 -->
<li>orange</li>
<li>banana</li> <!-- 奇數變色 -->
<li>grape</li>
<li>papaya</li> <!-- 奇數變色 -->
<li>coconut</li>
</ol>
<!-- CSS 程式碼 -->
<style>
ul li:nth-child(even) {color: red;} /* 偶數變色 */
ol li:nth-child(odd) {background: green;} /* 三的倍數變色 */
</style>
如果單純使用 n,也可當作一個「根據 An+B 公式自動擴展的序列」( n 從 1 開始計算 ),例如「2n」就等於「2,4,6,8....」,又或者「2n+2」就是「4,6,8,10...」,例如下方的例子,ul 裡偶數的 li 會是紅色,ol 裡的 li 則會使用三的倍數作為間隔變色。
<!-- HTML 程式碼 -->
<ul>
<li>apple</li>
<li>orange</li> <!-- 偶數變色 -->
<li>banana</li>
<li>grape</li> <!-- 偶數變色 -->
<li>papaya</li>
<li>coconut</li> <!-- 偶數變色 -->
</ul>
<ol>
<li>apple</li>
<li>orange</li>
<li>banana</li> <!-- 三的倍數變色 -->
<li>grape</li>
<li>papaya</li>
<li>coconut</li> <!-- 三的倍數變色 -->
</ol>
<!-- CSS 程式碼 -->
<style>
ul li:nth-child(2n) {color: red;} /* 偶數變色 */
ol li:nth-child(3n) {background: green;} /* 倒數奇數變色 */
</style>
:nth-last-child(n)
「:nth-child(n)
」表示「同一層元素裡,倒數第 n 個元素」,下方的 CSS 會將 body 裡,所有元素中倒數第二個子元素都變成紅色文字。
<!-- HTML 程式碼 -->
<ul>
<li>apple</li>
<li>orange</li>
<li>banana</li> <!-- ul 裡倒數第二個子元素 -->
<li>grape</li>
</ul>
<div>
<h2>oxxo.studio</h2>
<h3>hello world!!</h3>
<span><em>Yes</em> or <em>No</em></span> <!-- div 裡倒數第二個子元素 -->
<a>Google</a>
</div>
<!-- CSS 程式碼 -->
<style>
body * :nth-last-child(2) {color: red;} /* body 裡所有元素中從頭數來的第二個子元素呈現紅色文字 */
</style>
除了單除使用 :nth-last-child(n)
,如果在「開頭加上元素名稱」,就會表示「指定的元素的倒數第二個」,以下方的 CSS 為例,就會單獨將倒數第二個 li 變色,而不會影響到其他的元素。
body * li:nth-last-child(2) {color: red;} /* body 裡所有元素中倒數第二個 li 呈現紅色文字 */
:nth-last-child(n)
裡的 n 不僅可以只是數字,也可以使用奇數「odd」和偶數「even」這兩個英文單字,使用後就會自動「倒數」取得奇數項元素或偶數項元素。
<!-- HTML 程式碼 -->
<ul>
<li>apple</li> <!-- 倒數偶數變色 -->
<li>orange</li>
<li>banana</li> <!-- 倒數偶數變色 -->
<li>grap</li>
<li>papaya</li> <!-- 倒數偶數變色 -->
<li>coconut</li>
</ul>
<ol>
<li>apple</li>
<li>orange</li> <!-- 倒數奇數變色 -->
<li>banana</li>
<li>grap</li> <!-- 倒數奇數變色 -->
<li>papaya</li>
<li>coconut</li> <!-- 倒數奇數變色 -->
</ol>
<!-- CSS 程式碼 -->
<style>
ul li:nth-last-child(even) {color: red;} /* 倒數偶數變色 */
ol li:nth-last-child(odd) {background: green;} /* 倒數奇數變色 */
</style>
如果單純使用 n,也可當作一個會「根據 An + B 公式自動擴展的序列」( n 從 1 開始計算 ),例如「2n」就等於「...8,6,4,2」,又或者「2n+2」就是「...10,8,6,2」,例如下方的例子,ul 裡倒數偶數的 li 會是紅色,ol 裡的 li 則會使用三的倍數作為倒數間隔變色。
<!-- HTML 程式碼 -->
<ul>
<li>apple</li> <!-- 倒數偶數變色 -->
<li>orange</li>
<li>banana</li> <!-- 倒數偶數變色 -->
<li>grape</li>
<li>papaya</li> <!-- 倒數偶數變色 -->
<li>coconut</li>
</ul>
<ol>
<li>apple</li> <!-- 倒數三的倍數變色 -->
<li>orange</li>
<li>banana</li>
<li>grap</li> <!-- 倒數三的倍數變色 -->
<li>papaya</li>
<li>coconut</li>
</ol>
<!-- CSS 程式碼 -->
<style>
ul li:nth-last-child(2n) {color: red;} /* 倒數偶數變色 */
ol li:nth-last-child(3n) {background: green;} /* 倒數三的倍數變色 */
</style>
:only-child
「:only-child
」表示「同一層只有自己一個元素」,下方的 CSS 會將 body 裡,所有元素中只有一個子元素的子元素變成紅色文字。
<!-- HTML 程式碼 -->
<ul>
<li>apple</li>
<li>orange</li>
<li>banana</li>
<li>grape</li>
</ul>
<div>
<h2>OXXO.STUDIO</h2> <!-- 只有一個子元素,變色 -->
</div>
<div>
<h3>Hello World!!</h3> <!-- 只有一個子元素,變色 -->
</div>
<span><em>Yes</em> or <em>No</em></span>
<!-- CSS 程式碼 -->
<style>
body * :only-child {color: red;}
</style>
除了單除使用 :only-child
,如果在「開頭加上元素名稱」,就會表示「子元素只有一個指定元素」,以下方的 CSS 為例,就會單獨只有一個 h2 的 h2 變色,而不會影響到其他的元素。
body * h2:only-child {color: red;} /* body 裡所有元素中只有一個 h2 的 h2 變色 */
不過 :only-child
只針對有被標籤包覆的「元素」有作用,如果父元素裡有「純文字」,因為沒有被標籤包覆的緣故,純文字不屬於元素,也就不會影響 :only-child
的判讀,下方的範例中雖然 h3 後方有其他文字,但 h3 仍然會變色。
<!-- HTML 程式碼 -->
<ul>
<li>apple</li>
<li>orange</li>
<li>banana</li>
<li>grape</li>
</ul>
<div>
<h3>Hello World!!</h3> <!-- 只有一個子元素,變色 -->
我是純文字呦 <!-- 同一層裡有純文字 -->
</div>
<span><em>Yes</em> or <em>No</em></span>
<!-- CSS 程式碼 -->
<style>
body * :only-child {color: red;}
</style>
小結
CSS 和文件結構相關的虛擬類別選擇器非常好用,不但可以根據結構快速選取元素,更可以協助減少許多 JavaScript 邏輯判斷選取的功能,如果妥善運用,一定可以大幅簡化 CSS 程式碼,實現更好的排版方式與提升頁面效能。
意見回饋
如果有任何建議或問題,可傳送「意見表單」給我,謝謝~