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);
  });
}

瀏覽器自動執行:

  1. 截取舊狀態快照(::view-transition-old
  2. 執行回呼,更新 DOM
  3. 截取新狀態快照(::view-transition-new
  4. 在兩組快照之間執行交叉淡入淡出動畫

自訂過渡動畫

預設交叉淡入淡出

::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#跨文档动画