配了八年错位动画,每次加个元素都要回头改 nth-child 的 delay——今天 sibling-index() 把这件事彻底原生化了

做错位动画,元素越多越烦。

每次加一个卡片进去,就要回头把所有 nth-child 的 delay 重新写一遍——第 5 个的 delay 要改成 0.4s,第 6 个改成 0.5s,哪天产品说「首屏多放一个 banner」,整个动画的时序全要重来一遍。

这破事今天被两个 CSS 函数彻底修了。


两个函数,解决十年痛点

sibling-index()sibling-count() 是 Firefox 154(2026-08-18)刚稳定的新 API,加上之前 Chrome 138 和 Safari 26.2 的支持,全球覆盖率今天正式突破 70%,正式进入 Baseline Newly Available 阶段

  • sibling-index():返回元素在父容器所有子元素中的位置(第 1 个返回 1,第 2 个返回 2……)
  • sibling-count():返回父容器里一共有多少个子元素

用法简单到不敢相信:

/* 错位动画,一行搞定 */
li {
  transition-delay: calc(sibling-index() * 100ms);
}

/* 均分容器宽度 */
.item {
  width: calc(100% / sibling-count());
}

第一个元素的 delay 是 100ms,第二个 200ms,第三个 300ms——你一行都没改过,浏览器自己算出来的


到底比 nth-child 好在哪

旧做法是这样的:

/* 每次加元素都要回头补 */
li:nth-child(1) { --i: 0; }
li:nth-child(2) { --i: 1; }
li:nth-child(3) { --i: 2; }
li:nth-child(4) { --i: 3; }
/* ……到第 20 个的时候整个人都麻了 */

li {
  transition-delay: calc(0.1s * var(--i));
}

或者干脆用 JS 去 setProperty,全是运行时逻辑。

新做法:

li {
  transition-delay: calc((sibling-index() - 1) * 100ms);
}

就这一行,不管你有多少个 li,自动全部算对。

三个关键差异:

  1. 不需要编号:nth-child 要手工写每一条规则,sibling-index() 不需要
  2. 天然参与 calc():nth-child 是选择器,不能放进算式里;sibling-index() 是值函数,直接扔进 calc()
  3. 增删元素自动重算:在 JS 里动态插入一个元素,delay 全自动更新,不用改任何 CSS

实际场景:不只是错位动画

sibling-count()sibling-index() 组合可以玩出很多花样,不只是 delay 这么简单:

/* 径向布局:元素越多每个越窄,刚好占满一圈 */
.item {
  width: calc(100% / sibling-count());
}

/* 动态色彩梯度:越后面的元素色调越暖 */
.item {
  background: hsl(
    calc(200 + (sibling-index() / sibling-count()) * 160),
    65%,
    55%
  );
}

/* 最后一项特殊处理(结合 :last-child 使用)*/
.item:last-child {
  width: calc(100% / sibling-count() * 1.5);
}

浏览器支持现状

浏览器 版本
Chrome / Edge 138+(2025-06)
Safari / iOS Safari 26.2+(2025-12)
Firefox 154+(2026-08-18 新稳定)

70% 全球覆盖率,已经可以渐进增强使用。不支持的浏览器会忽略这两条声明,不影响布局。


下一步你可以做的事

  1. 找一个现有项目里用 JS 动态设置 index 的地方,换成 sibling-index(),直接删 JS
  2. 检查 caniuse.com/sibling-count,确认你的目标用户覆盖率是否达标
  3. 把 nth-child 手工编号规则搜出来,看哪些可以合并成一条 sibling-index() 公式

错位动画这件事,CSS 自己会认路了,不用再靠人肉编号。

评论区

0 条评论

登录后可评论。