先记住这个答案
:nth-child(An+B) 的计算方式是把 n 从 0 开始逐个代入,算出来的正整数就是被选中的子元素序号。比如 2n+1:n=0 得 1,n=1 得 3,n=2 得 5,所以选中第 1、3、5… 个元素。A 控制周期,B 控制偏移。0 和负数结果直接丢弃,不会报错。
n从 0 开始代入,结果为正才生效2n选偶数,2n+1选奇数-n+3只选前三个:nth-last-child从末尾倒着数
最常见的几个公式对应哪些元素
搞清楚公式之前,先记住一件事:子元素的序号从 1 开始,不是从 0 开始。第一个子元素是 1,第二个是 2,以此类推。
/* 偶数行:n=0→0(忽略) n=1→2 n=2→4 … */
tr:nth-child(2n) { background: #f5f5f5; }
/* 奇数行:等价于 odd */
tr:nth-child(2n+1) { background: #fff; }
/* 第 3 个及之后:n=0→3 n=1→4 n=2→5 … */
li:nth-child(n+3) { color: gray; }
/* 只选前 3 个:n=0→3 n=1→2 n=2→1 n=3→0(停) */
li:nth-child(-n+3) { font-weight: 700; }2n 可以简写成 even,2n+1 可以简写成 odd,写哪种都行,面试时知道它们等价就够了。
-n+3 是一个很实用的写法。因为 n 每增加 1,结果就减 1,所以从 3 递减到 1 之后就变成 0 和负数,被忽略。效果就是只选中前 3 个元素。想选前 5 个就写 -n+5,以此类推。
负数结果的丢弃规则
很多人第一次看到 -n+3 会疑惑:代入后出现 0 和负数怎么办?答案是直接忽略。浏览器只取公式结果大于 0 的那些序号,其余全部跳过。
这个规则让公式变得很灵活。比如只想选第 5 到第 10 个元素,可以写 :nth-child(n+5):nth-child(-n+10),同时满足两个条件:序号大于等于 5,并且小于等于 10。
/* 选中第 5 到第 10 个 */
li:nth-child(n+5):nth-child(-n+10) {
background: lightyellow;
}两个 :nth-child 拼在一起就是交集。第一个保证序号不小于 5,第二个保证不大于 10。这种写法在分页列表高亮当前页范围时特别有用。
按类型数和倒着数
:nth-last-child 和 :nth-child 的公式完全一样,区别只是从最后一个子元素开始往前数。:nth-last-child(1) 就是最后一个,:nth-last-child(-n+3) 就是最后三个。
:nth-of-type 只数同标签类型的元素。比如父元素里有 <h2>、<p>、<p>、<p>,p:nth-of-type(2) 选的是第二个 <p>,不管前面有没有 <h2>。而 p:nth-child(2) 要求它既是 <p> 又是第二个子元素,如果第二个子元素恰好是 <h2>,就什么都选不到。
这两个的区分是面试高频考点。简单记::nth-child 数所有兄弟,:nth-of-type 只数同类型的兄弟。
容易答错的地方
- 以为 n 从 1 开始
n是从 0 开始的,这样2n才能选到第 2 个元素(n=1 时 2n=2)。如果n从 1 开始,2n得到的是 2、4、6,虽然结果碰巧一样,但n+3就会得到 4、5、6,漏掉第 3 个,和实际效果对不上了。- 混淆 nth-child 和 nth-of-type
- 父元素里混了不同标签时,两者结果完全不同。
p:nth-child(1)是「第一个子元素,并且必须是<p>」,如果第一个子元素是<h2>,它就不匹配。而p:nth-of-type(1)是「第一个<p>类型的兄弟」,不管它前面有几个<h2>。
面试官还会怎么问?
怎么只选中最后三个元素?
用 :nth-last-child(-n+3)。和 :nth-child(-n+3) 选前三个是同一个思路,只是从末尾开始倒着数。
nth-child(2n of .active) 是什么意思?
这是 CSS Selectors Level 4 的新语法。of .active 表示只在匹配 .active 的子元素里计数,然后从中选偶数个。以前要实现这个效果只能靠 JavaScript,现在一行选择器就够了。不过旧版浏览器不支持 of S 语法,用之前要确认兼容性。
nth-child 和 nth-of-type 在什么情况下结果一样?
当父元素的所有子元素都是同一个标签类型时,两者完全等价。比如 <ul> 里全是 <li>,li:nth-child(2) 和 li:nth-of-type(2) 选的是同一个元素。只有父元素里混了不同标签,结果才会不同。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。