メインコンテンツへスキップ
Code & Craft
Web制作 約9分で読めます

Astro View Transitions API で SPA 風ページ遷移を実装する方法【2026年4月最新】

Astro 5.0で安定版となったView Transitions APIを使い、MPA構成のまま滑らかなページ遷移アニメーションを実装する方法を実例付きで解説。パフォーマンスとSEOを両立する次世代の実装パターンを紹介します。

はじめに:View Transitions が変えるMPAの体験

従来、滑らかなページ遷移アニメーションを実装するには React や Vue といった SPA フレームワークが必須でした。しかし、JavaScript バンドルサイズの増大やSEOの課題から、MPA(マルチページアプリケーション)への回帰が進んでいます。

そこで注目されているのが View Transitions API です。Astro 5.0(2025年12月リリース)では、この API が安定版として採用され、JavaScript をほぼ書かずに SPA ライクな遷移体験を実現できるようになりました。

本記事では、2026年4月時点の最新仕様に基づき、Astro View Transitions の実装方法を実例とともに解説します。

  • 従来の課題: SPA は遷移が滑らかだが、初期ロードが重く SEO が弱い
  • View Transitions の利点: MPA の SEO・パフォーマンスを保ちながら、視覚的な遷移体験を向上
  • 本記事で得られるもの: 実装コード、カスタマイズパターン、パフォーマンス最適化手法

View Transitions API とは?基礎知識と Astro での実装方式

View Transitions API の仕組み

View Transitions API は、ブラウザネイティブの API(Chrome 111+、Edge 111+ で stable、Safari 18.5+ でサポート開始)で、DOM の変更前後の状態を補間してアニメーションを生成します。

sequenceDiagram
    participant User as ユーザー
    participant Browser as ブラウザ
    participant DOM as DOM
    participant API as View Transitions API

    User->>Browser: リンククリック
    Browser->>API: document.startViewTransition()
    API->>DOM: 現在のDOMをキャプチャ
    Browser->>Browser: 新しいページを読み込み
    API->>DOM: 新しいDOMをキャプチャ
    API->>Browser: 2つの状態を補間アニメーション
    Browser->>User: 滑らかな遷移を表示

Astro における実装方式(2026年4月現在)

Astro では、<ViewTransitions /> コンポーネントを <head> タグ内に配置するだけで、全ページ遷移に自動適用されます。

基本実装例(layouts/BaseLayout.astro):

---
import { ViewTransitions } from 'astro:transitions';
---
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>{Astro.props.title}</title>
  <ViewTransitions />
</head>
<body>
  <slot />
</body>
</html>

この設定だけで、同一オリジン内のリンク遷移すべてに fade アニメーションが適用されます。


カスタムアニメーションの実装パターン4選

Astro では、CSS の view-transition-name プロパティを使って、要素ごとに異なるアニメーションを定義できます。

1. フェードイン/アウトのカスタマイズ

デフォルトの fade 遷移を調整する例です。

---
// pages/index.astro
import BaseLayout from '../layouts/BaseLayout.astro';
---
<BaseLayout title="トップページ">
  <main transition:animate="fade">
    <h1>ようこそ</h1>
  </main>
</BaseLayout>

<style>
  @keyframes fade-in {
    from { opacity: 0; }
  }
  @keyframes fade-out {
    to { opacity: 0; }
  }

  ::view-transition-old(root) {
    animation: 0.3s ease-out both fade-out;
  }
  ::view-transition-new(root) {
    animation: 0.3s ease-out both fade-in;
  }
</style>

2. スライドイン遷移(左→右)

ページ全体を水平スライドさせる例です。

<style>
  @keyframes slide-from-right {
    from {
      transform: translateX(100%);
    }
  }
  @keyframes slide-to-left {
    to {
      transform: translateX(-100%);
    }
  }

  ::view-transition-old(root) {
    animation: 0.4s ease-in-out both slide-to-left;
  }
  ::view-transition-new(root) {
    animation: 0.4s ease-in-out both slide-from-right;
  }
</style>

3. 要素単位のアニメーション(モーフィング)

特定の要素(例: ヘッダー画像)を共通要素として扱い、位置・サイズを補間します。

<!-- pages/blog/index.astro -->
<img 
  src="/hero.jpg" 
  alt="ブログヒーロー画像" 
  transition:name="hero-image"
  transition:animate="morph"
/>

<!-- pages/blog/[slug].astro -->
<img 
  src="/hero.jpg" 
  alt="記事ヒーロー画像" 
  transition:name="hero-image"
  transition:animate="morph"
/>

transition:name が同じ要素は、ページ間で同一要素として扱われ、位置・サイズが滑らかに変化します。

4. リスト項目のステージング遷移

リスト要素を順番にフェードインさせる例です。

---
const articles = await getCollection('blog');
---
<ul>
  {articles.map((article, i) => (
    <li 
      transition:name={`article-${i}`}
      style={`animation-delay: ${i * 0.1}s;`}
    >
      <a href={`/blog/${article.slug}`}>{article.data.title}</a>
    </li>
  ))}
</ul>

<style>
  li {
    animation: fade-in-up 0.4s ease-out both;
  }

  @keyframes fade-in-up {
    from {
      opacity: 0;
      transform: translateY(20px);
    }
  }
</style>

パフォーマンス最適化とアクセシビリティ対応

1. prefers-reduced-motion への対応(必須)

動きに敏感なユーザーのために、アニメーションを無効化します。

@media (prefers-reduced-motion: reduce) {
  ::view-transition-old(*),
  ::view-transition-new(*) {
    animation: none !important;
  }
}

2. 外部リンクへの遷移を除外

外部サイトへのリンクは通常遷移させます。

<a href="https://example.com" data-astro-reload>外部サイト</a>

data-astro-reload 属性を付けると、View Transitions が無効化されます。

3. 画像の事前読み込み(LCP 改善)

遷移先ページのヒーロー画像を事前ロードして、LCP(Largest Contentful Paint)を改善します。

---
import { ViewTransitions } from 'astro:transitions';
---
<head>
  <ViewTransitions />
  <link rel="preload" as="image" href="/hero.jpg" />
</head>

4. JavaScript バンドルサイズの監視

Astro の View Transitions は、約 3KB の JavaScript を追加します(gzip 圧縮後)。公式の @astrojs/prefetch と組み合わせると、遷移がさらに高速化されます。

npm install @astrojs/prefetch
// astro.config.mjs
import { defineConfig } from 'astro/config';
import prefetch from '@astrojs/prefetch';

export default defineConfig({
  integrations: [prefetch()],
});

ブラウザサポートとフォールバック戦略

2026年4月時点のサポート状況

ブラウザバージョンサポート状況
Chrome111+✅ Stable
Edge111+✅ Stable
Safari18.5+✅ Stable(2026年3月リリース)
Firefox未サポート⚠️ Behind flag(about:config)

フォールバック戦略

Astro では、非対応ブラウザでは自動的に通常のページ遷移にフォールバックされます。開発者が特別な対応をする必要はありません。

flowchart TD
    A[ユーザーがリンククリック] --> B{View Transitions API対応?}
    B -->|対応| C[アニメーション付き遷移]
    B -->|非対応| D[通常のページ遷移]
    C --> E[ページ表示完了]
    D --> E

実装時の注意点とトラブルシューティング

1. CSS の重複読み込み

ページ遷移後に CSS が再適用されない場合、<link> タグに data-astro-rerun を追加します。

<link rel="stylesheet" href="/global.css" data-astro-rerun />

2. JavaScript の再実行

DOM 操作スクリプトが遷移後に動作しない場合、astro:page-load イベントを使います。

<script>
  document.addEventListener('astro:page-load', () => {
    console.log('ページ遷移完了');
    // DOM 操作をここに記述
  });
</script>

3. アニメーションのちらつき防止

遷移前に要素が一瞬表示される場合、transition:persist を使います。

<nav transition:persist>
  <!-- ナビゲーションメニュー -->
</nav>

transition:persist を付けた要素は、ページ遷移時に DOM を保持し、再レンダリングを防ぎます


まとめ:View Transitions で MPA の UX を次のレベルへ

Astro View Transitions を使えば、SPA のような滑らかな遷移体験を、わずか数行のコードで実現できます。

重要なポイント:

  • Astro 5.0(2025年12月)で安定版、Safari 18.5(2026年3月)でクロスブラウザ対応が完了
  • <ViewTransitions /> コンポーネントを配置するだけで全ページに適用
  • transition:name で要素単位のモーフィングが可能
  • prefers-reduced-motion 対応は必須(アクセシビリティ)
  • 非対応ブラウザでは自動フォールバック、追加実装不要

次のステップとして、Astro 公式ドキュメント で高度なカスタマイズ方法を学ぶことをお勧めします。


参考リンク

#Astro #View Transitions #アニメーション #パフォーマンス最適化 #MPA
シェア: