CSS3出来那么久了,很多新特性都已经得到了主流浏览器的很好支持,相信很多人都在项目中使用过nth-of-type(n)以及nth-child(n)这两个选择器,这两个选择器功能很像,甚至在很多情况下使用的作用是相同的,但又有差异,容易给人造成困扰,我之前也是困扰了一段时间,查了忘,忘了查,浪费了很多时间。这里做一个测试以及梳理,以便查询参考记忆。
elt:nth-child(n):所干的事情分为两步
- 找到当前元素的父元素下所有的子元素。
- 在所有的子元素中找到第n个元素,如果找到的第n个元素,第n个元素是前面的elt类型或者类,符合前面elt规则要求(可能是类选择器,可能是元素选择器等)则被选中,应用相应的样式,否则不被选中,什么也不做。
- 如果是 elt :nth-child(n),elt后面,:前面有空格。则是寻找elt元素下的直接子元素中的第n个元素,无论第n个元素是什么类型或者类都会被选中。
elt:nth-of-type(n):所干的事情分三步
- 找到当前元素的父元素下的所有子元素的类型(nodeType)
- 找到每个类型对应的的所有元素,例如所有的div,p,h3
- 从第二步中每种元素类型中的元素中开始计数,并找到第n个元素,符合则应用样式规则,结果可能会选中多个元素,比如前面的条件是类选择器,而这个类选择器对应多个元素类型。
- 如果是elt :nth-of-type(n),elt后面,:前面有个空格,则是先找到elt元素下面的所有子元素类型包括子孙元素(嵌套了一层,然后对这个嵌套层的子元素做相同匹配),然后每个类型中的第n个元素选中应用样式。
举例代码结构如下:
<div class="box">
<div class="div_item">div 1</div>
<p class="p_item">p 1</p>
<h3 class="h3_item">h3 1</h3>
<div class="div_item">div 2</div>
<p class="p_item">p 2</p>
<h3 class="h3_item">h3 2</h3>
<div class="div_item">div 3</div>
<p class="p_item">p 3</p>
<h3 class="h3_item">h3 3</h3>
</div>
1.验证nth-child()
.p_item:nth-child(2) {
background: #c00;
}
.p_item:nth-child(3) {
background: #c00;
}
.h3_item:nth-child(3) {
background: #c00;
}
.box :nth-child(5) {
background: greenyellow;
}
.box :nth-child(6) {
background: greenyellow;
}
.box :nth-child(7) {
background: greenyellow;
}
如图结果所示:
第一个.p_item:nth-child(2)我们选择和.p_item同级所有元素,然后选择第二个元素,检验第二个元素的类是否是.p_item,是则变红。
第二个.p_item:nth-child(3),同理先选择所有同级元素,找到第三个元素,然后发现第三个元素不是.p_item类,而是h3_item类,所以不匹配什么也不做。
第三个条件.h3_item:nth-child(3),是作为上面的第二条件佐证存在,找到了第三个元素,然后发现也是h3_item类,符合条件所以选中,应用样式。
第四个,第五个,第六个.box :nth-child(5),.box :nth-child(6),.box :nth-child(7)三个连续的选择器选择了按次序的三个元素而前面的条件都是.box :,这个条件是查找.box下的所有子元素,不管这个子元素是什么类或者类型,只要符合第n个则被选中。
2.验证nth-of-type()
.div_item:nth-of-type(1) {
background: #c00;
}
.div_item:nth-of-type(2) {
background: #c00;
}
.box :nth-of-type(3) {
background: greenyellow;
}
第一个第二个条件:.div_item:nth-of-type(1),.div_item:nth-of-type(2)可以看到结果中我们选择到了第一个和第四个元素,并且这两个元素类型都是div。所以查找步骤是先查看冒号':'前面的条件的元素类型(nodeType),找到所有同级的相同元素类型的元素,这里是所有的div,然后从这些元素中选择第n个元素,这里是第1个div,和第2个div。他们在排序中分别是第1和第4。
第三个条件:.box :nth-of-type(3)是冒号':'距离前面条件有个空格,从结果中可以看到选择了.box下面所有类型的第三个元素,在这里是div中的第三个,p中的第三个,h3中的第三个元素。他的作用是,如果冒号距离前面的条件有个空格,则是找到前面条件元素下的所有子元素类型包括子孙元素(嵌套了一层,然后对这个嵌套层的子元素做相同匹配),然后找到每个子元素类型中的第n个元素。
这里还有一种情况的修改结构和条件如下:
<div class="box">
<div class="type_diff">type_diff 1</div>
<p class="type_diff">type_diff 2</p>
<h3 class="type_diff">type_diff 3</h3>
<div class="type_diff">type_diff 4</div>
<p class="type_diff">type_diff 5</p>
<h3 class="type_diff">type_diff 6</h3>
<div class="type_diff">type_diff 7</div>
<p class="type_diff">type_diff 8</p>
<h3 class="type_diff">type_diff 9</h3>
</div>
<style>
.type_diff:nth-of-type(2) {
background: greenyellow;
}
</style>
结果:
条件.type_diff:nth-of-type(2)明明是选择.type_diff对应元素类型第二个元素,一般来说只是一个元素,但是我们选择到了三个元素。这里并没有出现了bug。
我们可以看到.type_diff对应了三种元素类型div,p,h3。所以这里依然是一样的步骤,先找到.type_diff对应的元素类型,这里有三种,然后找到每种元素类型对应的第n个元素即可。原理是一样一样的。
关于上述空格问题其实就是说我们的冒号前面是父级元素情况,如果需要只匹配该层级子目录的元素则可以使用 .peltclass>:firstChild
补充一些常用选择方法:(可以衍生很多种)
nth-child(-n+2) :选择前2个元素
nth-child(n+3) :匹配>=3的元素
CSS3伪类选择器:nth-child()
简单的归纳下nth-child()的几种用法。
第一种:简单数字序号写法
:nth-child(number)
直接匹配第number个元素。参数number必须为大于0的整数。
例子:
li:nth-child(3){background:blue;}
第二种:倍数写法
:nth-child(an)
匹配所有倍数为a的元素。其中参数an中的字母n不可缺省,它是倍数写法的标志,如3n、5n。
例子:
li:nth-child(3n){background:red;}
第三种:倍数分组匹配
:nth-child(an+b) 与 :nth-child(an-b)
先对元素进行分组,每组有a个,b为组内成员的序号,其中字母n和加号+不可缺省,位置不可调换,这是该写法的标志,其中a,b均为正整数或0。如3n+1、5n+1。但加号可以变为负号,此时匹配组内的第a-b个。(其实an前面也可以是负号,但留给下一部分讲。)
例子:
li:nth-child(3n+1){background:red;}
li:nth-child(3n+5){background:blue;}
li:nth-child(5n-1){background:yellow;}
li:nth-child(3n±0){background:green;}
li:nth-child(±0n+3){background:orange;}
第四种:反向倍数分组匹配
:nth-child(-an+b)
此处一负一正,均不可缺省,否则无意义。这时与:nth-child(an+1)相似,都是匹配第1个,但不同的是它是倒着算的,从第b个开始往回算,所以它所匹配的最多也不会超过b个。
例子:
li:nth-child(-3n+8){background:red;}
li:nth-child(-1n+8){background:blue;}
第五种:奇偶匹配
:nth-child(odd) 与 :nth-child(even)
分别匹配序号为奇数与偶数的元素。奇数(odd)与(2n+1)结果一样;偶数(even)与(2n+0)及(2n)结果一样。