CSS 实现基于滚动的动画

24 年 3 月 17 日 星期日
908 字
5 分钟

起因

许多网页中会添加一些基于页面滚动的动画效果,用来丰富交互体验,吸引用户的注意力。在过去,这些效果往往是通过 JavaScript 监听滚动事件进行控制的。例如下面的图片展示了 Vercel 仪表盘页面头部在滚动时的动画效果。

Vercel 动画效果

PS: 这段 GIF 是通过 Kap 软件录制的,它是我正在使用的一个开源的录屏软件。你可以录制屏幕上的指定区域,快速编辑录制内容,并且支持多种导出格式例如:GIF。如果你感兴趣,可以去它的网站了解更多,🙏感谢开源社区!

我最近发现可以不使用 JavaScript,仅仅利用 CSS 属性就可以实现类似的效果。

实现原理

这里主要借助 animation-timelineanimation-range 这两个属性。

animation-timeline 用于指定控制 CSS 动画进度的时间轴。可以设置以下 3 种类型的时间轴。

  1. 文档时间轴,表示动画会在文档首次加载到浏览器之后,随时间进行。将 animation-timeline 设置为 auto 时或没有设置 animation-timeline 时按照该方式进行,这就是正常情况下 CSS 动画的运行方式。

  2. 滚动进度时间轴,表示通过可滚动元素的滚动位置,转换成对应的百分比来控制动画的进行。它有两种指定方式,一种是提供一个控制滚动时间轴的滚动条的名字;另外一种是使用 scroll() 函数指定一个匿名的滚动条。一般情况下直接使用 scroll() 即可,这表示使用距离当前元素最近的可滚动父级元素来控制动画的进行。更复杂的操作请查看相应的文档

  3. 视图进度时间轴,表示根据滚动条内元素的可见性来控制动画的进行。默认情况下,该元素首次进入滚动区域的一个边缘时,动画进度为 0%,到达另一个边缘时,动画进度为 100%。

animation-range 用来设置动画在时间轴上的开始和结束位置。

请看下面这个例子,假设有如下的 HTML 结构

html
<div class="container">
  <div class="square"></div>
  <div class="placeholder"></div>
</div>

container 元素和 placeholder 元素添加一些高度,使得 container 元素可以滚动。

css
.container {
  height: 500px;
  overflow-y: auto;
}
.placeholder {
  height: 1000px;
}
.square {
  margin-top: 100px;
  margin-left: 100px;
  width: 100px;
  height: 100px;
  background-color: red;
}

然后为 square 元素添加动画效果。

css
.square {
  animation: linear rotateAnimation both;
  animation-timeline: scroll();
  animation-range: 0 100px;
}
@keyframes rotateAnimation {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

上面的代码表示,当滚动条滚动从 0100px 时,square 元素会根据滚动条的位置旋转一圈。这样通过这两个属性的配合,就实现了页面滚动控制动画进度啦。

这是我模仿 ios 天气应用实现的一个基于滚动动画的例子。

兼容性

目前这两个属性都属于实验阶段,它们的浏览器兼容性并不好,具体的情况可以查看 Can I use 的说明。

所以应该避免在生产环境上使用,如果需要使用,最好做好相应的处理,例如可以将动画代码嵌套在 @supports 查询语句内。

css
@supports (animation-timeline: scroll()) {
  .square {
    animation-timeline: scroll();
    /* your code */
  }
}

参考

  1. MDN 上关于 animation-timeline 的介绍
  2. Can I use animation-timeline: scroll()

文章标题:CSS 实现基于滚动的动画

文章作者:柃夏chapu

文章链接:https://www.lxchapu.com/posts/css-scroll-driven-animation[复制]

最后修改时间:


商业转载请联系站长获得授权,非商业转载请注明本文出处及文章链接,您可以自由地在任何媒体以任何形式复制和分发作品,也可以修改和创作,但是分发衍生作品时必须采用相同的许可协议。
本文采用CC BY-NC-SA 4.0进行许可。