译者:@飘飘
作者:@Saron Yitbarek
https://webkit.org/blog/17101/a-guide-to-scroll-driven-animations-with-just-css/
前言
介绍了如何仅使用 CSS 实现滚动驱动的动画效果。详细讲解了滚动驱动动画的三个组成部分:目标、关键帧和时间线,并通过具体示例展示了如何使用 CSS 的 animation-timeline 属性实现滚动驱动动画。今日前端早读课文章由 @Saron Yitbarek 分享,@飘飘编译。
译文从这开始~~
自从 Apple 在 2007 年首次将 CSS 动画引入网页以来,这项技术已经发展得非常成熟。从最初简单的颜色渐变,到如今各种精美复杂的图像在页面上旋转、飞动,动画效果已经变得极为丰富。
但如果你想把这些动画与用户行为(比如滚动页面)结合起来,以往通常需要借助第三方库和 JavaScript 来实现,这无疑增加了代码的复杂度。好消息是,现在我们只需要写几行 CSS,就能创建滚动驱动的动画。
现在越来越多的浏览器支持滚动驱动动画,在 Safari 26 测试版中也已可用,让你可以轻松打造引人注目的网页效果。下面我来给你详细介绍一下如何实现。
滚动驱动动画的三大组成部分
一个完整的滚动驱动动画包含三个要素:
目标元素:也就是我们要进行动画处理的元素 关键帧:定义用户滚动时,这个元素发生了什么变化 时间轴:控制动画何时开始、何时结束
其中,前两个部分你可能已经很熟悉了:
目标元素:可以是页面上任何你想动起来的内容,怎么设计完全由你决定。 关键帧:就是标准的 CSS 动画写法,滚动驱动动画的效果很大程度上取决于动画本身的质量。
而第三个部分时间轴(timeline),可能对你来说还比较陌生,但它是实现滚动驱动动画的关键。
什么是时间轴?
动画就像一个序列,它从开始到结束,沿着一个时间线前进。网页中的默认时间线被称为 文档时间线(document timeline),它是以时间为基础的。
如果我使用默认的时间轴制作动画,那么动画会随着时间的推移而播放。举个例子:假设我有一个绿色圆圈要做颜色变化动画,使用默认时间线的话,我可以设置第一秒变成红色,第二秒变成蓝色,第三秒变成黄色。整个动画根据时间的推移来进行。
这种基于时间的动画方式,已经使用多年。直到 2023 年 6 月,CSS Animations Level 2 标准中引入了一个新属性:animation-timeline
,我们才可以不再依赖时间,而是用其他方式来驱动动画,比如页面的滚动。这就是滚动驱动动画的诞生背景。
滚动驱动动画不再依赖时间,而是使用了两种新的时间轴:
scroll () 时间轴 view () 时间轴
scroll () 时间轴
使用 scroll()
的动画不是根据时间推进,而是随着用户的滚动行为而变化。
只要用户开始滚动,动画就启动;用户停止滚动,动画也就暂停。这种方式让动画真正与滚动行为挂钩。
一个常见的例子是进度条动画。虽然网页本身已经有滚动条了,但用进度条来演示 scroll 驱动效果非常直观。
第一步:创建目标元素
假设我们为一个叫做 “A-School of Code” 的编程学校官网添加一个底部进度条,可以用 footer 的伪元素来实现:
footer::after {
content: "";
height: 1em;
width: 100%;
background: rgba(254, 178, 16, 1);
left: 0;
bottom: 0;
position: fixed;
}
这段代码会在页面底部生成一条细长的黄色进度条。
第二步:定义关键帧
我们创建一个名为 progress-expand
的动画,让进度条从左向右展开:
@keyframes progress-expand {
from { width: 0% }
to { width: 100% }
}
第三步:设置时间轴为 scroll ()
这会告知我的浏览器,动画仅在用户滚动时生效,从而使其成为滚动驱动的动画。
footer::after {
...
animation-timeline: scroll();
}
第四步:绑定动画属性
将动画与元素绑定起来,在进度条中添加我们的 animation
属性
footer::after {
...
animation: progress-expand;
animation-timeline: scroll();
}
注意:animation-timeline 必须写在 animation 之后,否则动画不会生效。
就这样,我们完成了一个基本的滚动驱动动画。
动画的可访问性与动效舒适性
在上线前,别忘了考虑动画是否会引起用户不适,尤其是对对动态视觉敏感的用户。
像进度条这样的缓慢小范围动画,一般不会引发不适。但像视差滚动、景深模糊、缩放等大面积动画,则更容易让用户感到头晕或不舒服。
我们可以使用媒体查询来避免这些问题:
@medianot(prefers-reduced-motion){
/* 在这里写动画 */
}
这样设置后,只有当用户没有开启 “减少动画” 偏好时,动画才会生效。在这种情况下,我认为我们的动画是安全的。
完整代码示例:
footer::after {
content: "";
height: 1em;
width: 100%;
background: rgba(254, 178, 16, 1);
inset-inline-start: 0;
bottom: 0;
position: fixed;
transform-origin: top left;
animation: grow-progress linear;
animation-timeline: scroll();
}
@keyframes grow-progress {
from { transform: scaleX(0); }
to { transform: scaleX(1); }
}
view()
时间轴
scroll()
时间轴的动画一旦用户开始滚动就会启动,无论动画元素是否出现在视口内。
但很多情况下,我们希望动画在元素真正进入视口的时候再开始,比如图片滑入、菜单展开、画廊显示等。
希望在元素出现在视口时激活时间轴,而不是在用户开始滚动时激活时间轴,为此,我们需要为动画使用不同的时间轴 —— view()
时间轴。
我们用一个简单的例子来演示:让一张图片在滚动到视口时从右侧滑入并淡入。
将从一篇使用占位符文本的基本文章开始,并在页面的不同部分插入几张图片。由于这些图片位于文章的较下方,所以在页面首次加载时它们并不在视口中。
第一步:目标元素
页面中的图片就是我们要进行动画的目标元素。
第二步:关键帧
我们希望图片从右边滑进来并逐渐变得清晰:
@keyframes slideIn {
0% {
transform: translateX(100%);
opacity: 0;
}
100% {
transform: translateX(0%);
opacity: 1;
}
}
第三步:设置 view () 时间轴
需要在我的图像标签中设置新的 animation-timeline ,以便当它在视口内时被激活。
img {
animation-timeline: view();
}
第四步:绑定动画属性
需要通过设置图像的 animation
属性将它们全部整合在一起。
记住,首先设置 animation 属性是很重要的。否则,这将无法正常工作。
img {
animation: slideIn;
animation-timeline: view();
}
这样,图片就会在进入视口时从右侧滑入并淡入。
优化动画范围:animation-range
你可能会注意到,图片在滑动到快出视口时才完成动画,这样对用户体验不太友好。
理想情况下,图片应该在滑到页面中间时就完成动画,这样用户能更好地欣赏它。
这时就可以使用 animation-range
属性来控制动画范围:默认范围是从 0% 到 100%,意味着从元素进入视口的第一像素开始,到完全离开视口时结束。
为了让我的用户能够更轻松地看到这些图片,我希望动画在滚动到视口大约一半的位置时停止。到那时,我希望图片找到自己的位置并保持不动。为此,我要将范围改为 0% 和 50%,如下所示:
img {
animation: slideIn;
animation-timeline: view();
animation-range: 0% 50%;
}
这样,图片进入到页面中间时动画就结束,停留原地,不再移动,提升了阅读体验。
同样,为了照顾对动态敏感的用户,在这种情况下,我的动画比进度条要大。我页面上的图片相当大,如果您没有预料到它们会移动并且滚动得太快,它们可能会一闪而过。这可能会让人感到不适。为了谨慎起见,我打算将此放入减少动态效果的查询中,因此我的最终代码将如下所示:
@media not (prefers-reduced-motion) {
img {
animation: slideIn;
animation-timeline: view();
animation-range: 0% 50%;
}
}
下一步探索
animation-timeline
和 animation-range
还有更多高级用法:
scroll()
和 view()
是函数,可以传参来自定义动画行为。可以指定哪个元素是 “滚动容器”(默认是最近的带滚动条的父元素)。 可选值包括: nearest
(默认)、root
和self
可以设置滚动方向:默认是 block
,也可以设置为inline
、x
或y
你可以尝试不同设置,打造独一无二的滚动动画效果。
未来我们还会介绍更多关于元素进入 / 离开视口时的动画处理方法。现在,不妨在 Safari 26 测试版中动手尝试这些新特性,提升你的网站或 Web App 的交互体验。

優(yōu)網(wǎng)科技秉承"專業(yè)團隊、品質(zhì)服務(wù)" 的經(jīng)營理念,誠信務(wù)實的服務(wù)了近萬家客戶,成為眾多世界500強、集團和上市公司的長期合作伙伴!
優(yōu)網(wǎng)科技成立于2001年,擅長網(wǎng)站建設(shè)、網(wǎng)站與各類業(yè)務(wù)系統(tǒng)深度整合,致力于提供完善的企業(yè)互聯(lián)網(wǎng)解決方案。優(yōu)網(wǎng)科技提供PC端網(wǎng)站建設(shè)(品牌展示型、官方門戶型、營銷商務(wù)型、電子商務(wù)型、信息門戶型、微信小程序定制開發(fā)、移動端應(yīng)用(手機站、APP開發(fā))、微信定制開發(fā)(微信官網(wǎng)、微信商城、企業(yè)微信)等一系列互聯(lián)網(wǎng)應(yīng)用服務(wù)。