CSS選擇器介紹( 3)

Sandy
UI/UX練功坊
Published in
10 min readDec 19, 2018

--

css虛擬類別介紹

選取子元素的「child」型虛擬類別

這些虛擬類別,可以選擇同一階層所有的「子元素」中符合條件者:

E:first-child (選取第一個子元素 E )

E:last-child (選取最後一個子元素 E )

E:nth-child(n) (選取第 n 個子元素 E )

E:nth-child(odd) (選取第奇數個子元素 E,第 1、3、5、7…個)

E:nth-child(even) (選取第偶數個子元素 E,第 2、4、6、8…個)

E:nth-last-child(n) (選取倒數第 n 個子元素 E )

E:only-child (選取唯一的子元素 E )

※ 注意:這邊的E寫的是子元素本身的標籤(子元素可以省略不寫,但虛擬類別與父元素之間要有半形空格),若不指定元素標籤的話,就會不區分元素類型只依順序計算。

實作範例如下:

ul li:first-child {
color: #f00;
}
ul li:last-child {
color: #00f;
}
ul li:nth-child(3) {
color: #0f0;
}
ul li:nth-last-child(3) {
color: #f0f;
}
.my-table :nth-child(odd) td {
background-color: #ccc;
}
.my-table :nth-child(even) td {
background-color: #ffffce;
}
.my-table p:only-child {
color: #f00;
}

查看範例:虛擬類別測試1、2

比較值得注意的是,可以將 :nth-child(n) 中的 n 寫成算式,這樣就能進行較複雜的選取了。
例如寫成 (3n) 就是選取 3 的倍數,第 3、6、9…個。進階一點寫成 (3n+2) 就是從第二個元素開始數,每三個子元素,因為這個算式會帶入 (3x0+2)、(3x1+2)、(3x2+2),就是第 2、5、8…個子元素。
若將算式設為 (2n) 結果就與設定為 (even) 一樣,都是選取到偶數個;若設為 (2n+1) 就與設定為 (odd) 一樣,會選取到奇數個。

.my-list2 :nth-child(3n) {
color: #00f;
}
.my-list2 :nth-child(3n+2) {
color: #f00;
}
.my-list3 :nth-child(2n) {
color: #f00;
}
.my-list3 :nth-child(2n+1) {
color: #00f;
}

查看範例:虛擬類別測試3、4

選取兄弟元素的「of-type」型虛擬類別

這些虛擬類別,可以選擇同一階層且「同一類元素」中符合條件者:

E:first-of-type (選取每個類別的第一個元素 E )

E:last-of-type (選取每個類別的最後一個元素 E )

E:nth-of-type(n) (選取每個類別的第 n 個元素 E )

E:nth-last-of-type(n) (選取每個類別的倒數第 n 個元素 E )

E:only-of-type (選取唯一的類別元素 E )

※ 注意:這邊E寫的是要選取的元素標籤,若省略的話(即不指定元素類別)每種類別都會被選取到,可以依需求選到複合的類別。

實作範例如下:

<html>
<head>
.wrap :first-of-type {
color:#f00;
}
</head>
<body>
<div class="wrap">
<h1>我是h1元素</h1>
<p>我是第1個段落元素</p>
<h3>我是h3元素</h3>
<p>我是第2個段落元素</p>
<h3>我是第2個h3元素</h3>
<p>我是第3個段落元素</p>
<h3>我是第3個h3元素</h3>
<p>我是第4個段落元素</p>
<h5>我是h5元素</h5>
<p>我是第5個段落元素</p>
</div>
</body>
</html>

以這個範例來說 :first-of-type 因為沒有指定要哪一個類別,所以每一個類別的第一個元素都會被選取,也就是 h1、p、h3、h5 這四種元素的第一個元素都會變成紅色文字。

查看Demo(範例1)

另外,我們再寫一個 :only-of-type 試試看,因為這個範例中只有 h1 和 h5 元素只有一個,其他元素都是不只一個,所以只有 h1 和 h5 變成藍色文字。

<html>
<head>
.wrap2 :only-of-type {
color: #00f;
}
</head>
<body>
<div class="wrap2">
<h1>我是h1元素</h1>
<p>我是第1個段落元素</p>
<h3>我是h3元素</h3>
<p>我是第2個段落元素</p>
<h3>我是第2個h3元素</h3>
<p>我是第3個段落元素</p>
<h3>我是第3個h3元素</h3>
<p>我是第4個段落元素</p>
<h5>我是h5元素</h5>
<p>我是第5個段落元素</p>
</div>
</body>
</html>

查看Demo(範例2)

否定虛擬類別

這個類別可以根據要排除的條件,一次選取其餘全部的元素,例如要做元素間的間距時很方便(除了第一個元素,其餘都設定 margin-top )。

E:not(s) (不含條件 s 的元素 E )

※ 注意:s條件可以是「虛擬類別」、「id/class選擇器」或「類型選擇器」

實作範例如下:

<html>
<head>
.my-list :not(:last-child) {
color: #f00;
}
.wrap :not(.text-b) {
color: #00f;
}
.block :not(p) {
text-decoration: underline;
color: #0f3;
}
</head>
<body>
<div class="wrap2">
<h1>我是h1元素</h1>
<p>我是第1個段落元素</p>
<h3>我是h3元素</h3>
<p>我是第2個段落元素</p>
<h3>我是第2個h3元素</h3>
<p>我是第3個段落元素</p>
<h3>我是第3個h3元素</h3>
<p>我是第4個段落元素</p>
<h5>我是h5元素</h5>
<p>我是第5個段落元素</p>
</div>
</body>
</html>

查看Demo範例

目標虛擬類別

E:target ( 選取「點擊時」 href 路徑所指向的目標元素 E )

※ 注意:這個虛擬類別,可以選取連結「目的地」的元素,而非連結本身的元素

先設定好 a 元素的連結 # 名稱,再將對應的 id 名稱綁在要顯示的區塊 ul 上,接著將 ul 元素預設隱藏( display: none; ),只有在點擊 a 連結時,對應的目的地 ul 元素(ul:target)才會顯示出來( display: block; ),要注意的就是 :target 並不是綁在 a 元素,而是綁定在 a 元素連結指向的「ul 元素」
如此,就用純 css 的寫法完成了一個簡易的展開收合 Menu。

<html>
<head>
ul {
list-style: circle;
display: none;
}
ul:target {
display: block;
}
</head>
<body>
<div class="wrap">
<a href="#content-1" class="menu-btn">Menu 1</a>
<ul id="content-1">
<li>list-01</li>
<li>list-02</li>
<li>list-03</li>
</ul>
<a href="#content-2" class="menu-btn">Menu 2</a>
<ul id="content-2">
<li>list-01</li>
<li>list-02</li>
<li>list-03</li>
</ul>
<a href="#content-3" class="menu-btn">Menu 3</a>
<ul id="content-3">
<li>list-01</li>
<li>list-02</li>
<li>list-03</li>
</ul>
</div>
</body>
</html>
點擊 a 元素(Menu 1) ,底下隱藏的 ul 元素就會顯示出來,可以切換點擊不同的 Menu

查看Demo範例

UI虛擬類別

可以依據「輸入表單的狀態」選擇元素的虛擬類別,可用來設定表單元素相鄰的 label 元素之樣式。

E:enabled (有效的表單元素 E )

E:disabled (禁用的表單元素 E )

E:checked (被選中的表單元素 E,例如單選/複選核取框)

實作範例如下:

<html>
<head>
/* 有效的input元素之label */
.myform input:enabled + label {
cursor: pointer;
}
.myform input:enabled + label:hover {
color: #037ef3;
}
/* 禁用的input元素之label */
.myform input:disabled + label {
color: #ccc;
}
/* 已勾選的input元素之label */
.myform input:checked + label {
border-bottom: 3px double #037ef3;
}
</head>
<body>
<form class="myform">
<input type="radio" name="radio" id="radio1" value="1" checked>
<label for="radio1">選項1</label>
<input type="radio" name="radio" id="radio2" value="2">
<label for="radio2">選項2</label>
<input type="radio" name="radio" id="radio3" value="3">
<label for="radio3">選項3</label>
<input type="radio" name="radio" id="radio4" value="4" disabled>
<label for="radio4">選項4</label>
</form>
</body>
</html>
使用UI虛擬類別,可以依據表單元素輸入的狀態來設定想要的樣式

查看Demo範例

總結:
「~child」型虛擬類別並不區分元素的類型,而是將所有的子元素列入計算
「~of-type」型虛擬類別會將不同類型的元素依據類型分開計算
「否定虛擬類別」的條件可以是虛擬類別、id/class選擇器或類型選擇器
「目標虛擬類別」和「 UI虛擬類別」好好運用可以省下不少工
這些 CSS3 選擇器支援 IE 9 以上的版本

--

--