scroll-timeline目前不能替代js监听实现通用滚动驱动动画,仅在固定高度滚动容器、合成层属性动画、chromium 115+等特定约束下可用,safari和firefox支持极差。

scroll-timeline 目前不能替代 JS 监听实现通用滚动驱动动画,它只在特定约束下可用,且浏览器支持极不均衡。
animation-timeline: scroll() 的实际可用范围很窄
这个函数看似简洁,但参数 scroll(nearest block) 或 scroll(root y) 依赖滚动容器的“可预测性”。一旦滚动源是 body 或 html,Chrome 就可能因无法缓存布局信息而频繁触发同步布局,滚动直接卡顿。更常见的是:你写了 scroll(root),结果发现动画压根没动——因为 Safari 和 Firefox 根本不解析该值,@supports (animation-timeline: scroll()) 在它们里面返回 false。
真正能稳定用起来的场景只有:
- 滚动容器是固定高度的
<section style="height: 100vh; overflow-y: scroll;"></section> - 目标元素已脱离文档流(
position: absolute或transform: translateZ(0)) - 动画只改
opacity、transform这类合成层属性,不碰width、top、z-index
@scroll-timeline 规则里最容易漏掉的三个硬性条件
自定义时间线必须显式满足三项,缺一不可,否则整个动画静默失效:
-
source必须指向一个真实存在、可滚动的 DOM 元素(overflow-y: scroll或auto),且不能被transform、contain或will-change隔离滚动上下文 -
orientation必须写成vertical或horizontal,不能省略,也不能用y/x替代 -
start和end必须带单位(0px、100vh、20%),不支持em、rem,也不能写成纯数字
典型错误是写成 @scroll-timeline foo { source: selector(#main); orientation: y; start: 0; end: 100%; }——三个地方全错,控制台却不会报错,只会让动画完全不执行。
animation-duration 是个占位符,但必须写
规范强制要求 animation 属性中包含 animation-duration,哪怕你用的是 animation: fade-in auto linear。这里的 auto 不是可选,而是必须;它会被滚动距离覆盖,但若写成 animation: fade-in linear(漏掉时长),整个动画在 Chrome 中也会静默失败。
另外两个常被忽略的配套项:
-
animation-fill-mode: both—— 否则元素在滚动开始前或结束后会“闪回”初始状态 -
animation-timeline必须和@keyframes定义在同一作用域(不能跨 CSS 文件或 Shadow DOM 边界)
移动端和层叠交互类动效根本不能靠 scroll-timeline
iOS Safari、微信 WebView、所有 Android 原生浏览器对 scroll-timeline 零支持,连 @supports 查询都返回 false。更关键的是:它无法驱动 z-index 变化,也不能协调多个卡片之间的相对位移与层级顺序。比如你想让第 3 张卡片在滚动到 60% 时浮到最上层,就必须用 JS 动态设 style.zIndex;想做“逐张浮起+微旋转”,也得靠 JS 控制多个 transform 分量的非线性组合。
真正需要兼容性或复杂交互的项目,IntersectionObserver + CSS variables + transform 仍是更可控、更易调试的选择。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











