View Transitions API 仅支持 SPA 内同步 DOM 更新的平滑过渡,不支持跨页面跳转;其快照机制依赖同一 document 上的 view-transition-name 元素成对存在且可绘制,异步操作、命名不一致或元素未挂载均导致动画失效。

View Transitions API 不支持跨页面平滑过渡。
它只对单页应用(SPA)内同一文档的同步 DOM 更新生效,点击 <a href="/next"> 或执行 location.href = "/next" 会卸载当前文档、加载新 HTML,此时 document.startViewTransition() 调用无效——旧快照拍不到,新快照根本没上下文。
为什么直接跳转没动画?
常见现象:调用 startViewTransition() 后页面硬跳转,控制台无报错,但动画完全不出现。
- 浏览器在导航触发时销毁当前 document,
startViewTransition()的快照机制失去载体 - 即使你在
click事件里调用它,DOM 更新还没发生,过渡就已提前结束 - 新页面的 CSS 伪元素
::view-transition-old和::view-transition-new在旧文档中不存在,无法匹配
SPA 中正确触发过渡的写法
必须把 startViewTransition() 包裹在真实、同步、已完成挂载的 DOM 更新操作外层。
- ✅ 正确:
document.startViewTransition(() => { app.innerHTML = renderPage('detail'); }) - ❌ 错误:
document.startViewTransition(() => { router.push('/detail'); })—— 这只是发导航指令,没改 DOM - ⚠️ 避免异步:
await fetch()、setTimeout或 Promise.then 放在回调里会导致快照提前拍完,动画中断 - Vue 用户需用
nextTick或await flushSync确保渲染完成;React 用户推荐flushSync包裹更新逻辑
view-transition-name 配对失败的典型原因
90% 的“没动画”问题其实卡在这一步:命名不一致或元素未挂载。
- 不能动态生成值:
view-transition-name: item-${id}前后id不同 → 匹配失败 - 元素必须已插入
document才能被拍快照;createElement后没append就调用过渡 → 快照为空 -
::view-transition-old(item)和::view-transition-new(item)必须大小写完全一致,且两端元素都设置了该属性 - 避免给无关元素加
view-transition-name,否则它们会被卷入过渡,干扰图层顺序
::view-transition-old 和 ::view-transition-new 的样式陷阱
浏览器把旧/新视图分别渲染为独立合成层,但很多 CSS 会让旧元素“不可绘制”,导致快照为空。
立即学习“前端免费学习笔记(深入)”;
- ❌ 禁止在快照前设
display: none、visibility: hidden或opacity: 0 - ✅ 可用
opacity: 0.001占位,或用backdrop-filter+ 半透背景模拟遮罩 - 自定义动画时务必统一
animation-duration,否则旧层早消失、新层晚入场,出现空白帧 - 调试时打开 DevTools 的 Layers 面板,确认目标元素进了带 “View Transition” 标签的独立合成层
view-transition-name 是否稳定成对、旧元素是否始终处于可绘制状态——这三点漏掉任一,过渡就静默失效。


















