当前位置:首页 > 文章列表 > 文章 > 前端 > CSS scroll-timeline 怎么驱动滚动进度动画

CSS scroll-timeline 怎么驱动滚动进度动画

来源:17golang原创 2026-09-28 04:37:23 0浏览 收藏
热门推荐
漫画APP
动画内容聚合,热门资源快捷查看
立即下载

scroll-timeline 的核心作用,是把滚动容器从起点到终点的位置映射成一条 0%~100% 的动画时间轴。把这条时间轴交给 animation-timeline 后,普通 @keyframes 就不再按经过的秒数推进,而是随用户向前或向后滚动而前进或回退。

最稳妥的入门方式是:在真正可滚动的容器上声明一个以 -- 开头的时间轴名称,再让进度条引用同一个名称。当前 MDN 仍把该能力标为 Limited availability,所以生产页面应把它当作渐进增强,而不是唯一可用路径。

官方参考:https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-timeline

标准草案:https://drafts.csswg.org/scroll-animations-1/

最小配方:命名滚动时间轴

下面的结构把文章内容放进一个固定高度、可纵向滚动的容器。进度条固定在容器顶部,初始宽度为完整宽度,再通过 scaleX() 从 0 缩放到 1。


一篇足够长的文章

这里放置能够产生纵向溢出的正文……

.article-shell {
  block-size: 70vh;
  overflow-y: auto; /* 必须真的可滚动,时间轴才会激活 */
  scroll-timeline: --reading block; /* 名称在前,滚动轴在后 */
}

.progress {
  position: sticky;
  inset-block-start: 0;
  inline-size: 100%;
  block-size: 4px;
  background: #2563eb;
  transform: scaleX(0);
  transform-origin: left center; /* 从左侧开始增长 */
  animation: grow 1ms linear both;
  animation-timeline: --reading; /* 必须写在 animation 简写之后 */
}

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

scroll-timeline 是 scroll-timeline-name 与 scroll-timeline-axis 的简写。名称必须是以 -- 开头的 dashed-ident;省略轴时默认为 block,它会随书写模式对应到块方向。这里明确写出 block,是为了让代码意图更直观。

animation-duration: 1ms 不代表动画只运行 1 毫秒。滚动时间轴接管后,真正决定进度的是滚动位置;保留一个极短 duration 主要是兼顾部分实现和旧示例习惯。更关键的规则是 animation-timeline 要放在 animation 简写之后,否则后出现的简写可能把时间轴重置为默认值。

滚动容器、命名时间轴、进度条与关键帧之间的静态绑定关系
图1:命名滚动时间轴的静态关系说明图;容器提供 --reading,进度条通过 animation-timeline 引用它。

滚动位置怎样变成关键帧进度

滚动进度时间轴关心的是“已经滚了多少”和“总共还能滚多少”的比例。以普通纵向容器为例,可以把它理解成下面这组关系:

可滚动范围 = scrollHeight - clientHeight
当前进度 = scrollTop / 可滚动范围

顶部位置  -> 0%
中间位置  -> 约 50%
底部位置  -> 100%

这段是概念说明,不需要在 JavaScript 中手动计算。浏览器会把滚动范围映射到时间轴,再用结果采样 @keyframes。用户向上滚时,动画同样会反向回退;停止滚动时,进度保持在当前位置。

如果容器没有溢出,可滚动范围为零,时间轴就无法产生有效进度。因此“CSS 写对了但动画不动”时,首先检查的不是关键帧,而是滚动源是否真的存在滚动条,以及内容高度是否超过容器。

什么时候直接用 scroll()

只有一个动画目标,而且它明确由最近的祖先滚动容器控制时,可以省略命名过程,直接使用匿名时间轴 scroll():

.card-progress {
  animation: grow 1ms linear both; /* 先声明关键帧动画 */
  animation-timeline: scroll(nearest block); /* 最近祖先的块轴滚动条 */
}

.page-progress {
  animation: grow 1ms linear both;
  animation-timeline: scroll(root block); /* 整个页面的根滚动区 */
}

scroll() 的滚动源可选 nearest、root 或 self,轴可选 block、inline、x 或 y。默认值是 nearest block。在横向轮播中,应明确写成 scroll(nearest inline) 或按实际书写模式选择 x。

多个元素需要共享同一个时间轴、滚动容器与动画目标距离较远,或者希望名称能表达业务语义时,命名 scroll-timeline 更易维护。只有一个局部效果时,匿名 scroll() 更短。两者都在做同一件事:选择滚动源与滚动轴,再把结果交给动画。

动画不生效时先查这五项

现象常见原因修正方式
完全不动容器没有溢出,或 overflow 为 hidden/clip给容器明确尺寸并保证内容超出
仍按时间播放animation 简写写在 animation-timeline 后面把 animation-timeline 放到简写之后
引用不到时间轴名称没有以 -- 开头,或声明与引用不一致统一使用例如 --reading 的名称
方向不对把 block/inline 与 x/y 混为一谈根据书写模式与实际滚动方向选择轴
部分浏览器无效果特性尚未达到 Baseline 广泛可用用 @supports 保留静态或 JS 降级

还有一个容易忽略的点:scroll-timeline 应声明在提供滚动位置的元素上,而 animation-timeline 应声明在真正执行关键帧的元素上。把两者全部写在进度条本身,除非进度条恰好也是滚动容器,否则往往选错滚动源。

兼容处理和无障碍降级

当前浏览器支持并不完全一致,最简单的策略是让基础页面在没有滚动动画时仍然可读,再只对支持 animation-timeline 的环境启用进度映射。

.progress {
  inline-size: 100%;
  transform: none; /* 默认保持静态可见,不依赖新特性 */
}

@supports (animation-timeline: scroll()) {
  .progress {
    transform: scaleX(0);
    transform-origin: left center;
    animation: grow 1ms linear both; /* 简写先出现 */
    animation-timeline: scroll(root block); /* 时间轴后出现 */
  }
}

@media (prefers-reduced-motion: reduce) {
  .progress {
    animation: none; /* 尊重减少动态效果的系统偏好 */
    transform: scaleX(1);
  }
}

如果阅读进度是业务必需信息,而不仅是装饰,可以再提供一个 JavaScript 降级:监听滚动并更新 CSS 自定义属性。但要避免在每个 scroll 事件里触发布局抖动,最好缓存容器尺寸、使用 requestAnimationFrame 合并更新,并在内容尺寸改变时重新计算。

滚动范围、变换映射、特性检测与减少动态效果之间的结构关系
图2:滚动进度映射与兼容边界说明图;支持时由时间轴控制变换,不支持或减少动态效果时保留静态可用状态。

可直接复用的完整片段

如果目标是整页阅读进度条,匿名根滚动时间轴最简洁。下面把结构、关键帧、特性检测和减少动态效果放在一起:



文章标题

正文内容……

.reading-progress {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 10;
  block-size: 4px;
  background: #2563eb;
  transform-origin: left center;
}

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

@supports (animation-timeline: scroll()) {
  .reading-progress {
    animation: reading-grow 1ms linear both; /* 设置关键帧与填充状态 */
    animation-timeline: scroll(root block); /* 用整页纵向滚动驱动 */
  }
}

@media (prefers-reduced-motion: reduce) {
  .reading-progress {
    animation: none; /* 减少动态效果时保留静态色条 */
    transform: scaleX(1);
  }
}

这个版本没有滚动事件监听,也不需要手动计算百分比。对支持滚动驱动动画的浏览器,它会随页面滚动平滑增长和回退;对不支持的环境,它仍是一条普通的静态提示条。若静态满格容易误导,可以在默认规则中改为隐藏,并在 @supports 内恢复显示。

几个常见问题

scroll-timeline 和 view-timeline 有什么区别?

scroll-timeline 关注滚动容器自身从起点到终点的滚动比例,适合阅读进度、轮播进度和整体视差。view-timeline 关注某个元素进入、穿过、离开滚动视口的可见过程,更适合元素入场动画。

为什么设置了 animation-duration 仍不能改变速度?

因为滚动时间轴用位置而不是经过时间驱动关键帧。duration 不再是“播放多久”的主要控制项。要改变视觉节奏,可以调整关键帧分布、缓动函数,或者换用更合适的滚动范围。

横向滚动该写 inline 还是 x?

inline 会跟随书写模式,适合国际化布局;x 始终指物理水平方向。组件跟随书写模式时优先使用 inline,明确固定为水平坐标轴时再使用 x。

scroll-timeline 能完全替代 JavaScript 吗?

纯视觉映射通常可以,但业务状态、复杂跨组件同步、旧浏览器支持和精确埋点仍可能需要 JavaScript。建议先把视觉效果做成渐进增强,再判断是否值得引入脚本降级。

scroll-timeline 最值得记住的不是某一段固定代码,而是三层关系:滚动容器提供时间轴,动画目标引用时间轴,关键帧描述 0% 到 100% 的视觉变化。只要滚动源、轴和声明顺序正确,阅读进度条这类效果就能用很少的 CSS 完成。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
photocolors色盘模式和记忆卡片模式怎么选?功能差异与使用场景photocolors色盘模式和记忆卡片模式怎么选?功能差异与使用场景
上一篇
photocolors色盘模式和记忆卡片模式怎么选?功能差异与使用场景
Go multipart.Reader ReadForm 怎么控制内存占用
下一篇
Go multipart.Reader ReadForm 怎么控制内存占用
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    247次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    293次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    262次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    243次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    51次使用