scroll-driven animations 是浏览器原生声明式滚动动画机制,依赖 @keyframes + animation-timeline: scroll();目前仅 Chromium 115+ 稳定支持,Firefox 和 Safari 尚未实现,需 JS 检测 + CSS 降级。

scroll-driven animations 是什么,浏览器支持现状如何
它不是 JavaScript 滚动监听 + 手动更新 CSS 的模拟方案,而是浏览器原生支持的声明式动画机制,靠 @keyframes + animation-timeline: scroll() 驱动。目前仅 Chromium 115+(Chrome、Edge、Opera)稳定支持,Firefox 和 Safari 尚未实现,scroll() 会直接被忽略,动画不触发——这不是 bug,是特性缺失。
这意味着:不能只写 animation-timeline: scroll() 就完事,必须配降级逻辑;也不能指望“写了就跨浏览器跑起来”。
怎么写一个最简可用的 scroll-driven 动画
核心三要素缺一不可:滚动容器(scroller)、目标元素(animating element)、时间线定义(timeline)。常见错误是漏掉 scroll-margin 或没设 overflow,导致 timeline 计算失败,动画静止不动。
-
scroll-margin必须加在动画元素上,告诉浏览器“以这个元素的哪个位置为锚点计算滚动进度”,例如scroll-margin: 100px 0 0 0表示顶部进入视口 100px 时开始动画 - 滚动容器(通常是
<body>或某个overflow-y: auto的块)必须有明确滚动行为,<body>默认可滚动,但若用了overscroll-behavior: none或重置了height,可能失效 - 动画本身用标准
@keyframes,但触发动画需显式指定animation-timeline: scroll(),且只能搭配animation-range或animation-scope控制区间
最小可行示例:
立即学习“前端免费学习笔记(深入)”;
div {
scroll-margin-top: 100px;
animation: fade-in 1s;
animation-timeline: scroll();
animation-range: entry 0% entry 100%;
}
@keyframes fade-in {
from { opacity: 0; }
to { opacity: 1; }
}
为什么加了 animation-timeline 却没反应
最常见的三个原因都跟“滚动上下文”有关:一是目标元素不在滚动容器的滚动流中(比如父级 position: fixed),二是滚动容器没有溢出内容(scrollHeight ≤ clientHeight),三是 scroll-margin 值过大或方向错配(如用 scroll-margin-bottom 但元素靠顶部触发)。
调试建议:
- 打开 Chrome DevTools → Elements → 选中动画元素 → 查看 Computed 面板里是否有
animation-timeline: scroll()生效(没生效说明被忽略) - 临时加
outline: 1px solid red看元素是否真在滚动流中渲染 - 用
getBoundingClientRect()手动检查元素 top 是否随滚动变化,确认它确实在滚动
需要兼容老浏览器时怎么安全降级
不能只靠 @supports (animation-timeline: scroll()) 包裹,因为 Safari/Firefox 不识别该语法,整个规则块会被丢弃,连基础 CSS 动画都没了。正确做法是把 scroll-driven 动画单独抽成 class,再用 JS 检测支持性后动态添加。
- 先写纯 CSS 过渡/动画作为默认效果(如
opacity: 0 → 1+transition) - 用
CSS.supports('animation-timeline', 'scroll()')判断,返回true再给元素加class="scroll-triggered" - 确保 class 中的 scroll-driven 规则不破坏原有样式(比如别覆盖
transition)
注意:JS 检测必须在 DOM ready 后执行,且要监听 resize,因为滚动容器尺寸变化可能影响 scroll-margin 的实际生效位置。
overflow: hidden。



















