做过列表动画的,今天 sibling-index() 把 nth-child 那套全删了

做过列表动画的都知道这个流程:写一个 fade-in,then 配 animation-delay,第一个 0ms,第二个 80ms,第三个 160ms……写到第七第八个就开始怀疑人生了。而且一旦中间加了新项,整个延迟链全要重新调。

这件事今天被两个 CSS 函数彻底变了:sibling-index() 和它的搭档 sibling-count()。

它怎么用

sibling-index() 会返回一个整数:当前元素是父元素的第几个孩子。从 1 开始数,第一个孩子返回 1,第二个返回 2,以此类推。它是个,不是选择器,所以可以直接塞进 calc() 做数学运算。

.item {
  animation: fade-in 400ms ease both;
  animation-delay: calc((sibling-index() - 1) * 80ms);
}

第一个元素的 delay 就是 (1-1)*80ms = 0ms,第二个 80ms,第三个 160ms——不用写一行 nth-child,所有项自动对齐,增删项也不需要改任何代码。

为什么比 nth-child 强

以前写级联动画,基本靠这个套路:

.card:nth-child(1) { animation-delay: 0ms; }
.card:nth-child(2) { animation-delay: 80ms; }
.card:nth-child(3) { animation-delay: 160ms; }
/* …写到第十个开始怀疑人生 */

nth-child 是选择器,匹配到了才生效,你没法拿它做数学。sibling-index() 返回的是一个数字,可以直接参与 calc() 运算——这就是本质区别。

搭配 sibling-count() 还可以做更复杂的动态布局,比如让最后一个元素反向动画:

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

@starting-style 把入场动画也包了

有了 sibling-index() 做延迟,@starting-style 补上了另一半:元素第一次出现时的入场动画。

@starting-style 的作用是给浏览器一个「元素刚出现时的状态」,让 transition 有一个起始点可以过渡——以前这件事要靠 requestAnimationFrame 双嵌套或者 setTimeout 硬凑。

.card {
  opacity: 1;
  transform: translateY(0);
  transition: opacity 0.4s ease, transform 0.4s ease;
}

@starting-style {
  .card {
    opacity: 0;
    transform: translateY(12px);
  }
}

两个配合起来,就是完整的「列表项依次入场」:

.item {
  animation: fade-in 400ms ease both;
  animation-delay: calc((sibling-index() - 1) * 80ms);
}

@keyframes fade-in {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: translateY(0); }
}

第一项立即入场,第二项等 80ms,第三项等 160ms——浏览器自己算,不用改一行 HTML 或 JS。

浏览器支持情况

sibling-index() 和 sibling-count() 已在 Chrome 138+、Edge 138+、Safari 26.2+ 稳定支持,Firefox 仍在实现中。使用 @supports 做渐进增强:

.item { animation: fade-in 400ms ease both; }

@supports (top: calc(1px * sibling-index())) {
  .item { animation-delay: calc((sibling-index() - 1) * 80ms); }
}

不支持的浏览器所有项同时淡入——功能降级,不是报错。

实际意义

以前列表入场动画必须靠 JS 读 DOM、塞 style 属性、监听增删——现在三行 CSS 全部去掉。这不是小优化,是把一个 JS 问题彻底还给了 CSS。

下一步:看看你的列表组件,找到那个 nth-child 链——现在可以删了。

评论区

0 条评论

登录后可评论。

小鹿·界面实验室 160 阅读