View Transitions API 實戰:跨頁面/跨文件動畫過渡方案
前端工程(更新於 2026年6月13日)
頁面過渡的演進
| 方案 | 適用範圍 | 實作複雜度 | 瀏覽器原生 | 效能 |
|---|---|---|---|---|
| CSS transition | 單元件 | 低 | ✅ | 高 |
| Framer Motion / GSAP | SPA 路由 | 高 | ❌ | 中 |
| Shared Element Transition | SPA + MPA | 低 | ✅ | 高 |
| View Transitions API | SPA + MPA | 低 | ✅ | 高 |
View Transitions API 讓瀏覽器自動處理舊→新狀態的快照、動畫和清理,開發者只需宣告「何時過渡」和「如何動畫」。
SPA 中的 View Transitions
基本用法:document.startViewTransition
function navigateTo(newRoute: string) {
if (!document.startViewTransition) {
updateDOM(newRoute);
return;
}
document.startViewTransition(() => {
updateDOM(newRoute);
});
}
瀏覽器自動執行:
- 截取舊狀態快照(
::view-transition-old) - 執行回呼,更新 DOM
- 截取新狀態快照(
::view-transition-new) - 在兩組快照之間執行交叉淡入淡出動畫
自訂過渡動畫
預設交叉淡入淡出
::view-transition-old(root) {
animation: 0.3s ease-in both fade-out;
}
::view-transition-new(root) {
animation: 0.3s ease-out both fade-in;
}
滑動切換效果
::view-transition-old(root) {
animation: 0.4s ease-in both slide-to-left;
}
::view-transition-new(root) {
animation: 0.4s ease-out both slide-from-right;
}
@keyframes slide-to-left {
to { transform: translateX(-100%); }
}
@keyframes slide-from-right {
from { transform: translateX(100%); }
}
共享元素過渡:跨元件動畫
給元素設定 view-transition-name,瀏覽器自動在舊→新位置間做 FLIP 動畫:
.card-image {
view-transition-name: card-img;
}
.card-title {
view-transition-name: card-title;
}
實戰:列表→詳情頁的 Hero 動畫
function openDetail(cardId: string) {
document.startViewTransition(() => {
document.querySelector('.list-page')!.style.display = 'none';
document.querySelector('.detail-page')!.style.display = 'block';
document.querySelector(`#card-${cardId} img`)!
.style.viewTransitionName = 'hero-image';
document.querySelector('.detail-hero img')!
.style.viewTransitionName = 'hero-image';
});
}
列表卡片圖片 → 詳情頁大圖之間自動做平滑縮放+位移動畫。
MPA 跨文件過渡
Chrome 111+ 支援跨文件(跨頁面導航)的 View Transitions:
啟用跨文件過渡
<meta name="view-transition" content="same-origin">
只需一行 meta 標籤,同源導航自動觸發交叉淡入淡出!
配合 CSS 自訂
@media (navigation: forward) {
::view-transition-old(root) { animation: slide-to-left; }
::view-transition-new(root) { animation: slide-from-right; }
}
@media (navigation: back) {
::view-transition-old(root) { animation: slide-to-right; }
::view-transition-new(root) { animation: slide-from-left; }
}
進階技巧
排除不需要動畫的元素
header, footer {
view-transition-name: none;
}
動態設定 view-transition-name
document.querySelectorAll('.card').forEach((card, i) => {
card.style.viewTransitionName = `card-${i}`;
});
等待圖片載入後再過渡
document.startViewTransition(async () => {
updateDOM(newRoute);
await document.querySelector('.detail-hero img')?.decode();
});
與工具庫的結合
效能考量
| 方面 | 建議 |
|---|---|
| 快照大小 | 避免對大尺寸元素設定 view-transition-name |
| 過渡時長 | 200-400ms 是感知最佳區間 |
| 並發過渡 | 多個共享元素同時動畫時 GPU 負載增加 |
| 版面配置抖動 | 回呼中避免觸發版面配置重排,否則快照不準確 |
常見問題
startViewTransition 回呼中可以非同步更新 DOM 嗎?
可以。回呼支援 async 函式,瀏覽器會等待 Promise resolve 後再截取新快照。但等待期間舊快照一直顯示,過長的等待會導致卡頓感。
跨文件過渡和 SPA 過渡的差異?
SPA 用 document.startViewTransition() 手動觸發,MPA 用 <meta name="view-transition"> 自動觸發。兩者共享同一套 CSS 偽元素和動畫定義。
如何除錯 View Transitions?
Chrome DevTools → Elements 面板可檢視 ::view-transition-group 等偽元素樹。Animation 面板可逐幀除錯過渡動畫。
總結
View Transitions API 將頁面過渡從手動 FLIP 計算變為瀏覽器原生快照+動畫,大幅降低實作複雜度。SPA 用 document.startViewTransition(),MPA 用 meta 標籤,共享元素用 view-transition-name——三種場景統一在同一套 CSS 偽元素體系下,是現代 Web 應用頁面過渡的最佳方案。
本站提供瀏覽器本地工具,免註冊即可試用 →
#View Transitions#页面过渡#MPA#SPA#跨文档动画