MPA で使う(クロスドキュメント遷移)

マルチページサイトでも、普通の <a href>location 遷移に View Transition を載せられる。Astro / Hugo / 静的サイト / 普通のサーバーレンダリングサイト全部に使える。 この learn-tech のような静的サイトはまさにこれ。

有効化は CSS の1行

同一オリジンへのナビゲーションに対して、ブラウザが自動で transition を挟むようになる。

どのページの CSS にも書く(共通スタイルが楽)
@view-transition {
  navigation: auto;
}

navigation: auto = 同一オリジンの普通のナビゲーション(リンククリック、フォーム submit、 history.back() 等)で transition を発火する。
navigation: none がデフォルト(無効)。

同一オリジン制限

クロスオリジンへの遷移では発火しない。同じオリジン内のページ間でしか動かない。 サブドメイン違いでもダメ(blog.example.comwww.example.com は不可)。

同じ name で hero 遷移

ページ A とページ B の両方で同じ view-transition-name を持つ要素を置けば、 その要素は別ページ間でもモーフする。

/blog/list.html
<a href="/blog/post-3.html">
  <img class="thumb" src="post-3.jpg" style="view-transition-name: post-3-image" />
</a>
/blog/post-3.html
<img class="hero" src="post-3.jpg" style="view-transition-name: post-3-image" />

ブラウザはページAでスナップショットを撮り、ナビゲーション後にページBでスナップショットを撮って繋ぐ。 JS は一切要らない

イベントで挙動をいじる

クロスドキュメント transition では、専用の2つのイベントを使ってアニメをカスタマイズできる。

イベント発火タイミング役割
pageswap 遷移元のページが消える直前 遷移元側で見せる「お別れ」アニメや、name の動的設定
pagereveal 遷移先のページが描画されてアニメが始まる直前 遷移先側のアニメ調整、active types の確認
遷移元(pageswap)でナビゲーション情報を見て分岐
window.addEventListener("pageswap", (e) => {
  if (!e.viewTransition) return // transition が走らないナビゲーション

  const from = new URL(e.activation.from.url)
  const to   = new URL(e.activation.entry.url)

  // 例: 詳細から一覧に戻るときは別の名前を使いたい
  if (to.pathname === "/blog/" && from.pathname.startsWith("/blog/")) {
    document.querySelector(".hero")?.style.setProperty("view-transition-name", "post-image")
  }
})
遷移先(pagereveal)で types を見て CSS を分岐
window.addEventListener("pagereveal", (e) => {
  if (!e.viewTransition) return

  const nav = navigation.activation
  if (nav.navigationType === "traverse" && isBack(nav)) {
    e.viewTransition.types.add("back")
  } else {
    e.viewTransition.types.add("forward")
  }
})

types を付けたら CSS で html:active-view-transition-type(forward) のように分岐すればよい。 詳しくは CSS と疑似要素 を参照。

「進む / 戻る」をブラウザの状態で判定

pagereveal 内でナビゲーション方向を取るには navigation.activation を使う。

function isBack(activation) {
  // 戻るナビゲーション(traverse)かつ現在のエントリより前
  return activation.navigationType === "traverse"
       && activation.entry.index < (activation.from?.index ?? 0)
}

SPA と MPA を併用する

Astro の <ClientRouter /> や同種のライブラリは「MPA だけど内部では fetch + DOM 入れ替え」で SPA 風に動く。結果として両方のメリットを取れるのが View Transition の強み。

このサイト(learn-tech)に試しに足してみる

assets/style.css に1行足すだけで、ページ間遷移にデフォルトのクロスフェードが付く。

@view-transition { navigation: auto; }

ロゴやナビ要素に view-transition-name を当てれば、 ヘッダがフラッシュせずそのまま居続けるような挙動も作れる。