浅析 nth-child(n) 和 nth-of-type(n)
首先看一个例子
<div> <p>第一个段落</p> <p>第二个段落</p> </div> p:nth-child(2) { background: red; } p:nth-of-type(2) { background: yellow; }
分别执行两段 css, 发现效果是一样的,如下:
但是如果文档的结构变得更加复杂呢?看下面一个例子:
<body> <h1>这是标题</h1> <p>这是副标题</p> <div> <p>第一个段落。</p> <p>第二个段落。</p> <p>第三个段落。</p> <p>第四个段落。</p> </div> <p>这是注释</p> <p>Internet Explorer 不支持 :nth-child() 选择器。</p> </body>
p:nth-child(2) { background: red; } p:nth-of-type(3) { background: yellow; }
此时的样式应该是怎样的呢?效果如下:
平时开发中对于 nth-child(n)和 nth-of-type(n) 常用在一些需要单独渲染的列表元素的选取上面,因为结构单一,所以不难区分,久而久之就容易对两者的用法产生混淆,虽然概念和用法都比较简单,但是一些教程和文档上面的描述比较绕,理解起来比较困难,所以这里针对上面的例子,通过集合的方式来简单的辨析一下两种元素选取方式的区别。
ele:nth-child(n)
选取父元素的第 N 个子元素,不论元素的类型。n 可以是数字(从 1 开始),关键词(even/odd),或者公式(3n + 1, 2n + 1...)
元素的选取方式和过程:
- 选取 ele 的父元素的所有一级子元素 => 集合 P(不分类型,若有多个 ele,则分别选取,最终生成多个集合)
- 在集合 P 中选取第 n 个,判断类型是否为 ele,若是,则返回元素,否则返回空
针对上例子,首先选取 p 元素的父元素的所有一级元素,形成集合,因为有多个 p 元素,所以要分别选取,最终形成两个子元素集合
body 下的所有子元素集合 P
[ <h1>这是标题</h1>, <p>这是副标题</p>, <div>...</div>, <p>这是注释</p>, <p>Internet Explorer 不支持 :nth-child() 选择器。</p>, ]
div 下的所有子元素结合 K
[ <p>第一个段落。</p>, <p>第二个段落。</p>, <p>第三个段落。</p>, <p>第四个段落。</p>, ]
在 P 中选取第 2 个元素 ——> 判断元素类型是否为 p ——> 是 ——> 返回此元素
<p>这是副标题</p>
在 K 中选取第二个子元素 ——> 判断元素类型是否为 p ——> 是 ——> 返回此元素
<p>第二个段落。</p>
ele:nth-of-type(n)
选取父元素的第 N 个类型为 ele 的子元素。
- 选取父元素的所有类型为 ele 的子元素 => 集合 N
- 选取这些子元素集合 N 中的第 n 个,并返回
第一步生成集合 M 和 N
[ <p>第一个段落。</p>, <p>第二个段落。</p>, <p>第三个段落。</p>, <p>第四个段落。</p>, ]
[ <p>这是副标题</p>, <p>这是注释</p>, <p>Internet Explorer 不支持 :nth-child() 选择器。</p>, ]
然后分别选取 M 和 N 中的第三项,返回:
<p>第三个段落。</p>
<p>Internet Explorer 不支持 :nth-child() 选择器。</p>
简单总结来说,nth-child(n) 可以理解为先无条件选择子元素,后选择对应序号的元素并判断类型是否符合
nth-of-type(n) 则是先根据类型选择子元素,然后直接选择对应序号的元素即可。
参考:https://juejin.im/post/59bce23c51882519777c5eb5
http://www.w3school.com.cn/cssref/selector_nth-child.asp