纯 CSS 滚动动画完全指南

举报
yd_287440731 发表于 2026/10/18 19:04:03 2026/10/18
【摘要】 纯 CSS 滚动动画完全指南滚动动画一直是前端开发中的热门话题。过去我们习惯用 JavaScript 监听 scroll 事件或引入 GSAP、ScrollMagic 等库来实现,但随着 CSS 的演进,现在仅用纯 CSS 就能实现相当丰富的滚动动画效果。本文将从基础到进阶,系统介绍几种纯 CSS 实现滚动动画的方案。 一、为什么选择纯 CSS?性能更好:浏览器可以对 CSS 动画做合成层...

纯 CSS 滚动动画完全指南

滚动动画一直是前端开发中的热门话题。过去我们习惯用 JavaScript 监听 scroll 事件或引入 GSAP、ScrollMagic 等库来实现,但随着 CSS 的演进,现在仅用纯 CSS 就能实现相当丰富的滚动动画效果。本文将从基础到进阶,系统介绍几种纯 CSS 实现滚动动画的方案。

一、为什么选择纯 CSS?

  • 性能更好:浏览器可以对 CSS 动画做合成层优化,避免主线程阻塞。
  • 零依赖:不需要引入任何 JS 库,包体积更小。
  • 渐进增强:配合 @supports 可以优雅降级。
  • 代码简洁:声明式写法,可读性强。

当然纯 CSS 也有局限,比如无法做复杂的滚动进度联动计算。但对于大部分"进场动画"场景,它已经足够。

二、方案一:animation-timeline: view() —— 滚动驱动动画

这是现代 CSS 最强大的滚动动画方案,属于 Scroll-driven Animations 规范。核心思想是:让动画的进度由元素在视口中的可见程度决定,而不是由时间决定。

基本用法

.card {
  animation: fade-up linear both;
  animation-timeline: view();
  animation-range: entry 0% cover 40%;
}

@keyframes fade-up {
  from {
    opacity: 0;
    transform: translateY(60px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

关键点解析:

  • animation-timeline: view():动画时间轴绑定到元素自身的可见性。
  • animation-range: entry 0% cover 40%:定义动画的触发区间。entry 0% 表示元素刚开始进入视口,cover 40% 表示元素覆盖视口 40% 时动画结束。
  • both:让动画在区间外保持首尾状态。

animation-range 常用关键字

关键字 含义
entry 元素从视口边缘进入的过程
exit 元素从视口离开的过程
cover 元素完全跨越视口的过程
contain 元素完全处于视口内的过程

例如 animation-range: entry 25% cover 50%,表示动画从"元素进入视口 25%"开始,到"元素覆盖视口 50%"结束。

错落进场效果

给一组卡片设置不同的 animation-range 起点,就能做出瀑布式错落出现的效果:

.card:nth-child(1) { animation-range: entry 0% cover 30%; }
.card:nth-child(2) { animation-range: entry 10% cover 40%; }
.card:nth-child(3) { animation-range: entry 20% cover 50%; }

三、方案二:animation-timeline: scroll() —— 滚动进度动画

如果说 view() 是"元素驱动",那么 scroll() 就是"滚动条驱动"。它把动画进度绑定到某个滚动容器的滚动位置。

.progress-bar {
  position: fixed;
  top: 0;
  left: 0;
  height: 4px;
  background: linear-gradient(90deg, #6a5acd, #00d2ff);
  transform-origin: left;
  animation: grow linear;
  animation-timeline: scroll(root);
}

@keyframes grow {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}

这段代码实现了一个顶部阅读进度条。scroll(root) 表示绑定到根滚动容器;也可以写 scroll(nearest) 绑定到最近的可滚动祖先。

还可以用 scroll(root block) 指定滚动轴(block 为垂直,inline 为水平),做横向滚动画廊的进度指示非常方便。

四、方案三:animation-timeline: --custom —— 命名滚动时间轴

当动画元素和滚动容器不是同一元素时,可以用 scroll-timeline-name 定义一个命名时间轴,再通过 animation-timeline 引用。

.scroller {
  overflow-y: auto;
  height: 300px;
  scroll-timeline-name: --my-scroller;
  scroll-timeline-axis: block;
}

.indicator {
  animation: grow linear both;
  animation-timeline: --my-scroller;
}

这样即使 .indicator 不在 .scroller 内部,也能跟随它的滚动进度播放动画,非常适合做"侧边进度指示器 + 内容区滚动"的布局。

五、兼容性与降级

Scroll-driven Animations 目前已在 Chromium 115+ 和 Safari 26 支持,Firefox 仍在推进中。稳妥做法是用 @supports 做降级:

@supports (animation-timeline: view()) {
  .card {
    animation: fade-up linear both;
    animation-timeline: view();
    animation-range: entry 0% cover 40%;
  }
}

/* 不支持时保持可见,避免内容消失 */
.card {
  opacity: 1;
}

关键原则:默认状态写成"最终可见",只有在支持滚动时间轴时才把初始态设为隐藏。否则不支持的浏览器里内容会永远不可见。

六、方案四:经典 :target / position: sticky 技巧

在 Scroll-driven Animations 普及之前,纯 CSS 还有两个实用技巧。

1. position: sticky 实现滚动吸附

粘性定位本身就是一个"滚动联动"效果。配合 top 值,可以做吸顶导航、分段滚动等:

.section-title {
  position: sticky;
  top: 0;
  background: #fff;
  z-index: 10;
}

2. :target 实现滚动锚点切换

利用 URL 锚点触发 :target,可以做纯 CSS 的"滚动到某节时高亮"效果:

section:target {
  animation: highlight 0.6s ease;
}

不过这种方式依赖点击跳转,不是真正的滚动监听,适用场景有限。

七、实战小例:滚动渐显卡片列表

综合以上,一个完整可用的例子:

<div class="list">
  <div class="card">卡片 1</div>
  <div class="card">卡片 2</div>
  <div class="card">卡片 3</div>
</div>
.list {
  display: grid;
  gap: 40px;
  padding: 40vh 20px;
}

.card {
  padding: 40px;
  border-radius: 16px;
  background: #f4f4ff;
  box-shadow: 0 8px 24px rgba(0,0,0,.08);
}

@supports (animation-timeline: view()) {
  .card {
    opacity: 0;
    transform: translateY(80px) scale(.96);
    animation: reveal linear both;
    animation-timeline: view();
    animation-range: entry 10% cover 35%;
  }
}

@keyframes reveal {
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

八、性能与注意事项

  1. 优先动画 transform 和 opacity,避免动画 width、height、top 等触发重排的属性。
  2. animation-range 的百分比是相对于"可见性范围",不是视口高度,初学时容易混淆,建议用 DevTools 的动画面板观察。
  3. 给 animation-timeline 配 linear 缓动,滚动时间轴下非线性缓动会显得别扭。
  4. 避免过度使用:每个元素都绑滚动动画会带来额外合成开销,列表很长时建议只对首屏附近元素启用。

九、总结

纯 CSS 滚动动画如今已经足够成熟:

  • view() 做元素进场渐显,是最常用、最简单的场景;
  • scroll() 做全局滚动进度条、视差;
  • 命名时间轴 打通跨元素联动;
  • @supports 降级 保证旧浏览器可用。

掌握这几套组合拳,你就能在不写一行 JavaScript 的前提下,做出流畅、优雅的滚动动画。随着浏览器支持度持续提升,scroll-driven animations 很可能会成为未来滚动交互的标准做法,值得尽早掌握。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。