Scroll-Triggered:滚到某处触发一次动画
Scroll Timeline 与 View Timeline 两页讲的是进度型:动画进度和滚动位置 1:1
绑定,滚动多少就播放多少,向回滚动则倒回(scrub)。这页是触发型:当滚动越过某个位置时,触发一段普通的、按时间播放的动画(如「进入视口即淡入」),本质是 IntersectionObserver 的纯 CSS 声明式替代。Chrome 145(2026)起支持,来源见
Chrome 官方博客。
1 · 进度型 vs 触发型
scroll-driven(Scroll / View Timeline):animation-timeline 把时间轴替换为滚动进度——动画没有自己的时长,停在何处取决于你滚到何处,可来回 scrub。
scroll-triggered(本页):动画仍是按时间播放(有 duration、easing),只是何时开始播放由滚动位置触发;越过触发点正放,退出时倒放。适合「一次性的入场 / 退场」,不适合「随滚动连续跟随」。
2 · 三个新属性
| 属性 | 作用 |
|---|---|
timeline-trigger / -name / -source |
定义一个具名触发器:基于某条 timeline(view() / scroll())在指定 offset 上触发。 |
animation-trigger |
把元素的 animation 绑定到某个触发器,并指定进入 / 退出各做什么动作。 |
trigger-scope |
限定触发器名字的可见范围(类比 timeline-scope / anchor-scope),让触发器能被作用域内的元素引用。 |
timeline-trigger 的语法是 timeline-trigger: --name source 激活区间 / 活跃区间;。激活区间(activation range)越过就触发动画;斜杠后的活跃区间(active range)决定触发态保持多久,且必须包住激活区间。区间沿用 view-timeline 的关键字:entry 100% exit 0%
即 contain,entry 0% exit 100% 即 cover。
animation-trigger 的语法是 animation-trigger: --name <正向动作> <反向动作>;,把动画绑到触发器上。目前确认的动作有 play-forwards(正放)与 play-backwards(倒放),完整动作集见
CSS Animations Level 2 规范。
3 · 官方示例(纯 CSS,无 JS)
@keyframes card { from { translate: 0 -50% 0; } }
.card {
overflow-y: clip;
timeline-trigger: --t view() contain 15% contain 85% / entry 100% exit 0%;
trigger-scope: --t;
animation: card var(--duration) ease-in-out both;
animation-trigger: --t play-forwards play-backwards;
}
卡片进入「contain 15% ~ 85%」区间时触发,活跃范围放宽到整个 entry → exit;animation-trigger 让它进入时正放、离开时倒放。
4 · DEMO · 当下即可运行——IntersectionObserver 等价版
在框内上下滚动。卡片进入视口时淡入上移(正放),离开时反向退出(倒放)——这正是 scroll-triggered 想用纯 CSS 表达的行为。
5 · DEMO · 未来的纯 CSS 版(需 Chrome 145+)
同样的滚动框,但不写一行 JS,依靠 timeline-trigger + animation-trigger 实现。在不支持的浏览器里,animation-trigger 被忽略,卡片保持初始(隐藏)态。
怎么选? 要「随滚动连续跟随」(进度条、视差、随滚动连续变形)用 scroll-driven(Scroll / View Timeline);要「滚到即播放一次」的入场 / 退场动画,以前得写 IntersectionObserver,如今用 scroll-triggered 一行 CSS 即可实现,还自带「退出倒放」。两者都建立在同一套 view() /
scroll() timeline 与 range 关键字之上。