view-timeline 仅 chrome/edge 115+ 支持,firefox/safari 不支持且静默退化;需与 animation-timeline: view() 配对使用,二者名称一致、位置合规,且元素须有真实渲染尺寸并处于滚动流中,animation-range 定义可见进度而非时间。

Chrome/Edge 115+ 才能用 view-timeline 驱动动画,Firefox 和 Safari 完全不支持——写了也不会报错,但动画静默退化成普通时间线,看起来“完全不动”。
view-timeline 和 animation-timeline: view() 必须配对写
view-timeline 本身只是给元素打标记,不触发动画;真正驱动的是 animation-timeline: view()。两者名称必须一致,且不能跨层级乱放:
-
view-timeline: --vt;要写在目标元素(或其有渲染尺寸的祖先)上,DevTools 的 Computed 面板里搜不到这个值,说明没生效 -
animation-timeline: view(--vt);必须写在要动画的那个元素上,不能写在父容器或::before/::after里 - 如果目标元素是
position: fixed或套了transform,view()会直接失效——加outline: 1px solid red滚动看它动不动,不动就是被隔离出滚动流了
animation-range 控制“哪一段可见度触发动画”
animation-range 不是控制时间,而是定义动画在元素“可见进度”中的起止点。它的单位是元素自身高度的百分比,不是视口高度:
-
animation-range: entry;:从顶部刚进视口(0% 可见)→ 完全进视口(100% 可见) -
animation-range: contain;:从完全进视口(100%)→ 开始离开(99% 可见),适合“只在中间段动画” -
animation-range: entry 20% exit 80%;:动画从元素 20% 高度进入视口时开始,到只剩 80% 高度在视口内时结束 - 别写
0% 100%——这是scroll()的语法,在view()下非法,Chrome 会忽略整条声明
元素必须有真实渲染尺寸且在滚动流中
view() 依赖浏览器持续计算元素可见高度,以下任一不满足,动画就卡死:
- 元素
height为 0(比如空<div></div>、display: none、父级height: 0),getBoundingClientRect().height返回 0 时,view()直接放弃 - 被
contain: paint、overflow: hidden或clip-path截断边界,浏览器无法准确判断可见区域 - 父容器用了
overscroll-behavior: contain或none,滚动事件传播被阻断
最容易被忽略的是:View Timeline 的进度不是线性映射到滚动像素,而是基于“当前可见高度 / 元素自身高度”,所以元素高度动态变化(比如图片懒加载后撑开)会导致动画节奏跳变——如果需要稳定节奏,优先考虑 @scroll-timeline + scroll() 方案,或降级用 IntersectionObserver。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











