A是步长(非零整数),决定间隔;B是偏移量,决定起始位置,但A×0+B≥1才生效;两者均基于子元素在DOM中的1-based全局序号,而非视觉位置或类型。

什么是 An+B 里的 A 和 B
A 是步长,必须是非零整数,决定“隔几个选一个”;B 是偏移量,决定“从第几个开始”,但最终匹配位置必须 ≥ 1。两者都不直接对应“第几行”或“第几列”,只作用于子元素在 DOM 中的全局序号(从 1 开始)。
比如 :nth-child(3n+1):代入 n = 0, 1, 2, 3...,得到序号 1, 4, 7, 10...,不是“每组第一个”,而是所有满足该等差数列的位置。
常见误操作:
- 把
B当成“起始索引”却忽略n从 0 开始 → 实际第一个匹配项是A×0 + B = B,所以B必须 ≥ 1 才能生效 - 写
:nth-child(2n+0)期望匹配偶数位 → 无效,因为结果为 0,而位置不能为 0;应写:nth-child(2n)(浏览器自动解释为2n+0,但要求n≥1,即匹配 2, 4, 6...) - 用负
A却没控制n范围 →:nth-child(-2n+5)匹配的是 5, 3, 1(n=0→5,n=1→3,n=2→1,n=3→-1无效),本质是“倒数前几个”,不是周期性选择
:nth-child(-n+3) 为什么能选前三个?
它不靠周期,而靠 n 取值有限:当 n = 0 → -0 + 3 = 3,匹配第 3 个;n = 1 → -1 + 3 = 2;n = 2 → -2 + 3 = 1;n = 3 → 0,停止。所以只匹配第 1、2、3 个子元素。
这种写法适合静态截断,但要注意:
- 它和
:nth-child(1), :nth-child(2), :nth-child(3)效果相同,但更紧凑 - 一旦父容器里插入新节点(如中间加了个
<hr>),序号全乱,第 3 个可能变成<hr>,样式就套错元素 - 不能和
:nth-of-type混用预期 ——div:nth-child(-n+3)要求第 1–3 个子元素恰好都是div,否则不匹配
Grid 布局中改列数后 An+B 必须重算
CSS Grid 本身不理解“第几列”,:nth-child() 也看不到视觉网格,只数 DOM 顺序。所以“每三列后清空一行”这类需求,实际是靠公式定位到那个“该跨行”的子项。
例如三列 Grid 中让第 4、7、10… 项满宽:
.grid > :nth-child(3n+4) { grid-column: 1 / -1; }
如果列数改成 4,原来第 4 项还在第一行末尾,但新逻辑要让它出现在“每四列之后”,就得改成 :nth-child(4n+5)(因为 n=0→5,即第五项才是新周期的起点)。
容易被忽略的点:
- 公式不是按“显示位置”算的,是纯数学生成序列,和
grid-template-columns值无关,但人工推导时必须对齐列数 - 若 Grid 子项中夹杂非
grid-item元素(如标题<h2></h2>),它们也占序号,3n+4就会错位到错误元素上 - 没有自动适配机制 —— 列数响应式变化(如
@media改repeat(2, 1fr))时,公式无法动态切换,得配合类名或 JS 重置
JavaScript 模拟 :nth-child(An+B) 的关键转换
DOM API 返回的 NodeList 或数组是 0-based,而 :nth-child 是 1-based,转换时别漏 +1。
通用筛选逻辑:
function nthChild(array, a, b) {
const result = [];
for (let n = 0; ; n++) {
const pos = a * n + b; // CSS 中的位置(1-based)
if (pos array.length) break;
result.push(array[pos - 1]); // 转回 0-based 索引
}
return result;
}
调用示例:nthChild(items, 3, 1) 对应 :nth-child(3n+1),返回第 0、3、6… 索引的元素(即 DOM 中第 1、4、7… 个)。
注意边界:
-
a === 0时,pos === b恒成立 → 相当于只取第b个,但需确保b ≥ 1且 ≤array.length a 时,循环必须加 <code>pos ≥ 1判断,否则可能死循环- 不要用
%模拟 ——index % a === b % a在多数情况下不等价,尤其b为负或a不整除时
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











