写了八年滚动动画,今天发现整个 JS 库都可以删了——CSS scroll-driven animations 把这件事彻底变了

以前写滚动动画,要在 JS 里监听 scroll 事件、算位置、塞 requestAnimationFrame,三个文件起步,还动不动卡顿。2026 年了,这套方案基本可以淘汰了。

CSS scroll-driven animations——滚动驱动动画——现在稳住了:Chrome 115+、Firefox 126+、Safari 18+ 全球覆盖率约 90%,生产环境直接用,不用 polyfill。

两个时间轴,搞定所有场景

核心就两个函数:

scroll() 绑定页面整体的滚动进度:

.progress-bar {
  animation: grow linear;
  animation-timeline: scroll();
}
@keyframes grow {
  from { transform: scaleX(0); }
  to { transform: scaleX(1); }
}

滚动多少,动画就走多少,可进可退。

view() 绑定元素在视口中的可见性:

.card {
  animation: fade-in linear both;
  animation-timeline: view();
  animation-range: entry 0% cover 40%;
}
@keyframes fade-in {
  from { opacity: 0; transform: translateY(30px); }
  to { opacity: 1; transform: translateY(0); }
}

元素进入视口时开始动画,40% 可见时结束。不用 IntersectionObserver,不用 scroll 监听。

animation-range 控制触发时机,entry / exit / cover / contain 四个关键词,可以混百分比做精确控制。

真实案例:Tokopedia 减少了 80% 的滚动代码

这不是概念演示。Chrome 官方博客收录了三个生产案例:

  • Tokopedia:把原来的 JS 滚动实现迁移到 CSS scroll-driven animations,代码行数减少 80%,滚动时平均 CPU 占用从 50% 降到了 2%。
  • redBus:移动端图片瀑布流和桌面端 Cover Flow 动画,原来各写一套 JS,现在用 view() 一套 CSS 全搞定。
  • Policybazaar:保险对比表格,滚动时自动缩小低优先级元素、行标题,滚动停顿时保持对比焦点,不需要 JS 介入。

三个案例都是电商场景,滚动行为复杂、用户量大,迁移之后性能和体验同步提升。

性能为什么好

关键在「不在主线程跑」。JS scroll 监听是异步的,浏览器滚动和 JS 回调天然不同步。scroll-driven animations 是声明式 CSS,浏览器在合成线程上处理,不占用主线程 JS 执行时间。

实测:页面里塞一个 heavy JS 循环阻塞主线程,CSS 滚动动画完全不受影响,JS 版直接卡顿。

生产注意事项

Firefox 目前需要 animation-duration: 1ms 才能触发滚动驱动,写上去对其他浏览器无害。

每次用 animation 简写会重置 animation-timeline,用 longhand 或者在简写之后单独声明 animation-timeline。

无障碍:始终把无动画状态作为默认可见状态,把动画层叠在 @supports (animation-timeline: scroll()) 和 @media (prefers-reduced-motion: no-preference) 里面,这样 Firefox 用户和关闭动画的用户看到的是完整内容,不是空白。

下一步

如果你的项目还在用 ScrollMagic、GSAP ScrollTrigger 或者手写 scroll 监听,可以开始评估迁移路径了。reading progress indicator、parallax、entrance reveal 这三类场景迁移成本最低,先拿这几个试水。整个链路只需要几行 CSS,没有依赖,没有 bundle 体积增加。

2026 年了,这件事终于不用靠 JS 了。

评论区

0 条评论

登录后可评论。

阿柯·前端架构 74 阅读