滚动动画不再需要库
CSS scroll-driven animations 把视差、进度条、入场序列从 JS 里解放出来。记录一次真实的替换过程。
把个人站点上最后一个滚动监听器删掉的那天,我意识到一件事:过去五年我们用 GSAP 和 IntersectionObserver 做的事情,有一大半已经是浏览器的原生了。
进度条的三行写法
以阅读进度条为例。旧的写法需要一个 scroll 监听器,每次滚动算一遍 scrollTop / (scrollHeight - clientHeight),再写回 DOM。现在的写法是纯 CSS:
.progress {
transform-origin: left;
animation: grow linear both;
animation-timeline: scroll(root);
}
@keyframes grow { from { transform: scaleX(0); } to { transform: scaleX(1); } }
三行,没有 JS,跑在合成器上。主线程再忙它也不掉帧——这是任何 JS 滚动库都给不了的保证。
两个坑
迁移过程踩过两个值得记下来的坑。第一是作者顺序:动画的最终状态必须写在普通样式里,时间线包在 @supports 里做增强,顺序反了,不支持的浏览器会看到一个被 both 钉在起始帧的空页面。第二是「已在视口里的东西不要映射到滚动」——文章标题的入场如果绑定滚动进度,页面一加载它就直接是完成态,因为它本来就在首屏;这类元素该用加载时钟,不该用滚动轴。
另外别忘了 prefers-reduced-motion:滚动驱动的动画是「响应用户输入的刷子」,本身不算前庭风险,但和入场动画叠在同一批元素上时,reduce 用户应该看到的仍然是完整的页面,而不是一堆被钉住的中间态。
什么时候还用库
当然它也有边界。需要 pin 住一段滚动、需要 seek 到某个时间点、需要多元素之间的复杂编排——这些还是 GSAP 的地盘。我的判断标准很简单:如果一个效果只关心「滚动到哪了」,用原生;如果它关心「滚动过程中的戏剧结构」,上库。
工具在变,判断力不变。知道每个东西能做什么不难,难的是知道什么时候不用它。
本文章采用 CC BY-NC-SA 4.0 许可协议。
评论
尚未接入评论区还没有接入。这个站用
giscus(GitHub Discussions)承载留言: 在src/components/Comments.astro里填入仓库配置即可启用,步骤见项目 README。