CSS3选择器的 nth-child 与 nth-of-type

吐槽

CSS3 的选择器文档说明简直让人看的头大,每一句话都搞得跟阅读理解一样,就算读通了也没有办法理解,所以就在这里好好研究一下 CSS3 的选择器到底选择目标是什么。

nth-child

官方解释:p:nth-child(2) 规定属于其父元素的第二个子元素的每个 p 的背景色

最难让我头大的就是这个 nth-child 本身不难理解,就是选择对应父级的第 n 个节点元素,比如:

1
2
3
4
5
6
7
8
9
/* 基础样式,分离每个 .wrapper 下的子元素 */
.wrapper>* {
border: 2px solid pink;
margin: 5px 0;
}

.wrapper :nth-child(2) {
background-color: skyblue;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<div class="wrapper">
<p>i'm p</p>
<div class="inner">
<ul>
<li>2222</li>
<li>2222</li>
<li>2222</li>
</ul>
<ul>
<li>2222</li>
<li>2222</li>
<li>2222</li>
</ul>
</div>
<li>2333</li>
<li>2333</li>
<li>2333</li>
<li>2333</li>
<li>2333</li>
<li>2333</li>
<p>i'm p too</p>
<p>i'm div</p>
</div>

但是恶心就恶心在,在这里使用的伪类是后缀与一个空选择器上,所以就直接表示为父元素的第二个子元素,那么如果我们为其前面加上一个 li,那就变成了:

1
2
3
.wrapper li:nth-child(2) {
background-color: skyblue;
}

经过一翻思想斗争,终于悟出了这里的语法解释意思为:选择 .wrapper 下的每个 li 元素,然后看这个 li 元素是否是其父级元素的第二个子元素,如果是就应用样式,如果不是就不应用样式。

我们要理解普通选择器是向下查找,每次添加条件,而伪类是用来过滤选择到的元素。

last-child

1
2
3
.wrapper li:last-child {
background-color: skyblue;
}

first-child

1
2
3
.wrapper li:first-child {
background-color: skyblue;
}

nth-of-type

官方解释:p:nth-of-type(2) 选择每个p元素是其父级的第二个p元素

我们按照刚才的思路去理解这个选择器,其流程为:选择 .wrapper 下的所有 li 元素,如果其在当前的同类型的兄弟节点中排第二个,那么就应用样式,否则不应用:

1
2
3
.wrapper li:nth-of-type(2) {
background-color: skyblue;
}

但是如果前面不加 li,而应用于 .wrapper 下的每个元素,那么就会变成:

1
2
3
.wrapper :nth-of-type(2) {
background-color: skyblue;
}

这个是因为没有规定子级的过滤元素,那么在匹配到每个新的标签类型时,都会验证其在兄弟节点相同的标签类型下,其是否是第2个,如果是就应用样式,如果不是就不应用样式

权重问题

CSS 的伪类选择器权重与 class 选择器权重是同等级的,举个例子:

1
2
3
4
5
6
<div class="wrapper">
<div class="child">div</div>
<div class="child">div</div>
<li class="child">li</li>
<li class="child">li</li>
</div>
1
2
3
4
5
6
7
.wrapper .child {
background-color: pink;
}

.wrapper :nth-of-type(2) {
background-color: skyblue;
}

同等级下,伪类选择器的效果覆盖了 class 选择器

1
2
3
4
5
6
7
.wrapper :nth-of-type(2) {
background-color: skyblue;
}

.wrapper .child {
background-color: pink;
}

调换位置后,class选择器覆盖了伪类选择器的效果