用 View Transitions API,SPA 页面过渡动画真就几行代码的事
用 View Transitions API,SPA 页面过渡动画真就几行代码的事
做了这么多年前端,你有没有被页面过渡动画折腾过?
SPA 项目要做页面切换动画,要么用 framer-motion 这种重武器,引入一大堆依赖,bundle 体积多出几十 KB;要么自己手写 CSS transition + JS 生命周期,一不小心就出现闪白、布局抖动、焦点丢失一系列问题。
我一直觉得这事不应该这么复杂。页面切换不就是”旧页面消失,新页面出现”么,浏览器作为最懂渲染的软件,为什么不能帮我们干这事?
好消息是,Chrome 111+ 开始支持的 View Transitions API,就是浏览器给前端开发者递过来的一把钥匙。严格说这算 CSS 特性,但它本质上是浏览器层面的动画引擎——你不用再手动管理新旧 DOM 的叠加和过渡,浏览器直接帮你截图、变换、补间动画。
上个月我把手头一个 React 资讯站点的路由切换从 framer-motion 迁移到 View Transitions API,bundle 体积直接减了 80KB(没错,就光这一个动画库的重量),而且过渡流畅度肉眼可见地提升了。
它的工作原理不复杂
API 的表面就一个方法:document.startViewTransition()。但背后浏览器的操作其实挺聪明:截取当前页面快照,执行 DOM 更新,截取新页面快照,用伪元素叠加做 crossfade 过渡,完成后清除伪元素。用 GPU 合成,不阻塞主线程。
最简单的实战:给 SPA 路由加过渡
function navigate(url) {
document.startViewTransition(() => {
document.getElementById(‘content’).innerHTML = getPageContent(url);
history.pushState({}, ”, url);
});
}
document.addEventListener(‘click’, (e) => {
const link = e.target.closest(‘[data-link]’);
if (link) {
e.preventDefault();
navigate(link.getAttribute(‘href’));
}
});
就这么三四行改动,不需要 npm install,不需要 import 任何库。页面切换自动带淡入淡出效果。
自定义动画
默认的 crossfade 确实有点无聊。好在 API 暴露了伪元素让你完全控制动画:
::view-transition-old(root) {
animation: slide-out 0.3s ease-out;
}
::view-transition-new(root) {
animation: slide-in 0.3s ease-out;
}
这样就是左滑出 + 右滑入的效果,手感更接近原生 App 的导航。
真正的杀手锏:多元素独立过渡
.site-header { view-transition-name: header; }
.content-area { view-transition-name: content; }
页头保持不动,内容区淡入淡出——共享元素过渡,不用手动实现。
MPA 跨页面导航也能有过渡
@view-transition {
navigation: auto;
}
一行 CSS,多页应用也能有过渡动画。Chrome 126+ 支持。
和 React 配合
React 并发模式下需要用 requestAnimationFrame 嵌套确保 DOM 变更已经提交到真实 DOM。
实际效果对比
| 指标 | framer-motion | View Transitions |
|---|---|---|
| Bundle 大小 | ~80KB min | 0(浏览器内置) |
| 实现复杂度 | 中等 | 低(一行 JS) |
| GPU 加速 | 取决于属性 | 始终 GPU 合成 |
| 跨页面导航 | 不支持 | 原生支持 |
如果你的目标用户是 Chrome/Edge 为主的群体,完全可以替代 framer-motion 的页面过渡功能。
兼容性兜底
if (document.startViewTransition) {
document.startViewTransition(updateFn);
} else {
updateFn();
}
2026 年了,浏览器的原生能力已经远比我们想象的要强。把那些几十 KB 的动画库从 dependencies 里挪走吧。
评论区
登录后可评论。












