nth-child() 选中元素天经地义,但它从来不告诉你选中的是第几个——Chrome 今天补上了这个十年的缺口

写过 CSS 的人都踩过这个坑:列表要加错位动画,得靠 JS 或者 Sass 循环给每个元素手动注入 --index,更土的办法是写十几条 :nth-child() 规则——浏览器明明知道每个元素是第几个,偏偏 CSS 拿不到这个值。Chrome 153 正式支持了 sibling-index()sibling-count(),这个问题现在用一行 CSS 解决了。

拿浏览器早就知道的数据

nth-child() 是选择器,它告诉你”哪些元素该选中”;sibling-index() 是函数,它告诉你”当前元素排在第几个”。这是本质区别——一个挑元素,一个返回值。两者完全不重复。

li {
  /* 第 1 个:100ms,第 2 个:200ms,第 3 个:300ms……自动算好 */
  animation-delay: calc(sibling-index() * 100ms);
}

sibling-count() 返回父元素下所有子元素的总数。配合 sibling-index() 就能做”相对位置”样式:

/* 最后一个元素特殊处理,不需要 :last-child */
li:last-of-type {
  /* 实际上等价于 sibling-index() == sibling-count() */
}

两者都返回整数,可以直接塞进 calc()min()max()round() 以及三角函数里,没有任何类型转换的麻烦。

几个直接能抄的写法

彩虹色列表,不用预处理器,不用 JS:

li {
  background: hsl(calc(360deg / sibling-count() * sibling-index()) 70% 60%);
}

反向错位,让最后一个先动、第一个最后动:

.card {
  animation-delay: calc((sibling-count() - sibling-index()) * 80ms);
}

自动等宽分栏,加一个子元素自动重新分配,不需要媒体查询:

.tab {
  width: calc(100% / sibling-count());
}

进度感 step X of Y

li::after {
  content: "第 " counter(sibling-index) " / " counter(sibling-count) " 步";
}

浏览器支持情况

MDN 已将其标记为 Baseline 2026——Chrome 和 Safari 的最新稳定版均已支持,Firefox 态度积极,WebKit 已在 Safari 26.2+ 落地。由于不支持的浏览器会直接忽略,未支持环境下仍是空白,不破坏任何已有行为,可以放心做渐进增强:

@supports (width: sibling-index(1)) {
  li {
    width: calc(100% / sibling-count());
  }
}

现在可以删掉的代码

以前要实现同样的效果,得在 JS 里写:

document.querySelectorAll(".card").forEach((card, i) => {
  card.style.setProperty("--index", i + 1);
  card.style.setProperty("--count", cards.length);
});

或者用 Sass 循环硬编码几十条 :nth-child 规则。现在一行 CSS 搞定,浏览器自己算。

sibling-index()sibling-count() 的意义不只是”少写点代码”——而是 CSS 终于能问浏览器”你刚才建的那个 DOM 树,里面是什么结构”,让样式层直接拿到了以前只有 JS 才能拿到的信息。

评论区

0 条评论

登录后可评论。

阿柯·前端架构 9 阅读