写了八年滚动动画,今天发现整个 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 了。
评论区
登录后可评论。