Astro 5.0 View Transitions で SPAライクなMPA を実装する【2026年5月最新】
Astro 5.0の View Transitions API を活用し、MPA の SEO メリットを保ちながら SPA 風のスムーズな画面遷移を実装する方法を解説します
Astro View Transitions がもたらす MPA の新しい可能性
従来、MPA(Multi-Page Application)は SEO に強い反面、ページ遷移時に画面全体が再読み込みされるため、ユーザー体験が SPA(Single-Page Application)に劣るとされてきました。
しかし Astro 5.0(2025年12月リリース) では、View Transitions API のサポートが大幅に強化され、MPA でありながら SPA のようなスムーズな画面遷移を実現できるようになりました。この記事では、Astro 5.0 における View Transitions の実装方法と、実プロジェクトで活用する際のベストプラクティスを解説します。
この記事で解決できること
- Astro 5.0 で View Transitions を有効化する基本設定
- ページ間遷移時のアニメーション制御
- 共通要素(ヘッダー・画像など)の遷移維持
- パフォーマンスとアクセシビリティの両立
- フォールバック戦略とブラウザ対応
Astro 5.0 View Transitions の基本実装
Astro 5.0 では、<ViewTransitions /> コンポーネントを使用することで、ページ遷移時に自動的にスムーズなアニメーションが適用されます。
基本セットアップ
まず、レイアウトファイルに ViewTransitions コンポーネントを追加します。
---
// src/layouts/BaseLayout.astro
import { ViewTransitions } from 'astro:transitions';
---
<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>
これだけで、ページ間のナビゲーション時にデフォルトのフェードアニメーションが適用されます。
View Transitions の動作フロー
sequenceDiagram
participant User as ユーザー
participant Browser as ブラウザ
participant Astro as Astro Router
participant API as View Transitions API
User->>Browser: リンククリック
Browser->>Astro: ナビゲーションイベント
Astro->>API: document.startViewTransition()
API->>Browser: 現在のページをキャプチャ
Astro->>Astro: 新しいページの HTML を fetch
Astro->>Browser: DOM を更新
API->>Browser: トランジションアニメーション実行
Browser->>User: スムーズな画面遷移
上記のシーケンス図は、Astro が内部的に View Transitions API を呼び出し、DOM の更新とアニメーションを制御する流れを示しています。従来の MPA では「リンククリック → 画面全体のリロード」という単純なフローでしたが、Astro では JavaScript によるクライアントサイドルーティングに切り替わります。
共通要素の遷移維持:transition:persist と transition:name
View Transitions の強力な機能の一つが、ページ間で共通の要素を維持し、アニメーションさせることです。
transition:persist による状態維持
transition:persist ディレクティブを使用すると、要素の状態(再生中の動画、フォーム入力、スクロール位置など)がページ遷移後も保持されます。
---
// src/components/MusicPlayer.astro
---
<div transition:persist="music-player">
<audio controls>
<source src="/music/bgm.mp3" type="audio/mpeg">
</audio>
</div>
この例では、ページ遷移しても音楽プレイヤーの再生状態が維持されます。transition:persist="music-player" の値は、ページ間で要素を一意に識別するための ID です。
transition:name によるモーフィングアニメーション
transition:name を使うと、ページ間で同じ名前を持つ要素が自動的にモーフィング(形状変化)アニメーションします。
---
// src/pages/blog/[slug].astro
const { slug } = Astro.params;
const post = await getPost(slug);
---
<article>
<img
src={post.image}
alt={post.title}
transition:name={`post-image-${slug}`}
class="w-full h-64 object-cover"
/>
<h1>{post.title}</h1>
<div set:html={post.content} />
</article>
一覧ページ側でも同じ transition:name を指定します。
---
// src/pages/blog/index.astro
const posts = await getPosts();
---
<div class="grid grid-cols-3 gap-4">
{posts.map(post => (
<a href={`/blog/${post.slug}`}>
<img
src={post.image}
alt={post.title}
transition:name={`post-image-${post.slug}`}
class="w-full h-48 object-cover"
/>
<h2>{post.title}</h2>
</a>
))}
</div>
これにより、一覧ページのサムネイルをクリックすると、画像が滑らかに拡大しながら詳細ページに遷移します。
カスタムアニメーションの実装
デフォルトのフェードアニメーションではなく、独自のアニメーションを定義することも可能です。
CSS によるカスタムトランジション
---
// src/layouts/BaseLayout.astro
import { ViewTransitions } from 'astro:transitions';
---
<html lang="ja">
<head>
<ViewTransitions />
<style is:global>
/* 新しいページがスライドインする */
::view-transition-new(root) {
animation: slide-in 0.3s ease-out;
}
/* 古いページがスライドアウトする */
::view-transition-old(root) {
animation: slide-out 0.3s ease-out;
}
@keyframes slide-in {
from {
transform: translateX(100%);
}
to {
transform: translateX(0);
}
}
@keyframes slide-out {
from {
transform: translateX(0);
}
to {
transform: translateX(-100%);
}
}
</style>
</head>
<body>
<slot />
</body>
</html>
JavaScript によるプログラマティック制御
Astro 5.0 では、astro:before-preparation や astro:after-swap などのライフサイクルイベントをフックできます。
---
// src/layouts/BaseLayout.astro
---
<script>
document.addEventListener('astro:before-preparation', (event) => {
console.log('ページ遷移準備中:', event.to.pathname);
// ローディングインジケーターを表示
document.body.classList.add('is-loading');
});
document.addEventListener('astro:after-swap', () => {
console.log('DOM 更新完了');
// ローディングインジケーターを非表示
document.body.classList.remove('is-loading');
// Google Analytics などのトラッキングコードを再実行
if (typeof gtag !== 'undefined') {
gtag('config', 'GA_MEASUREMENT_ID', {
page_path: window.location.pathname,
});
}
});
</script>
パフォーマンスとアクセシビリティの考慮
View Transitions を使用する際は、パフォーマンスとアクセシビリティのバランスを取ることが重要です。
プリフェッチによる高速化
Astro 5.0 では、data-astro-prefetch 属性を使ってページを事前読み込みできます。
<nav>
<a href="/" data-astro-prefetch>ホーム</a>
<a href="/about" data-astro-prefetch>会社概要</a>
<a href="/blog" data-astro-prefetch>ブログ</a>
</nav>
プリフェッチ戦略は3種類あります。
| 戦略 | 説明 | 使い所 |
|---|---|---|
hover | リンクにホバーした時に読み込み | デフォルト・デスクトップ向け |
tap | リンクをタップした時に読み込み | モバイル向け |
viewport | リンクが画面内に入った時に読み込み | ファーストビューの次のコンテンツ |
設定ファイルでデフォルト戦略を変更できます。
// astro.config.mjs
export default {
prefetch: {
defaultStrategy: 'viewport',
prefetchAll: true
}
}
アクセシビリティ対応
View Transitions は視覚的なアニメーションを伴うため、motion sensitivity(動きに敏感なユーザー)への配慮が必要です。
/* prefers-reduced-motion が有効な場合はアニメーションを無効化 */
@media (prefers-reduced-motion: reduce) {
::view-transition-new(root),
::view-transition-old(root) {
animation: none;
}
}
また、スクリーンリーダー使用者のために、aria-live 領域でページ遷移を通知することも推奨されます。
<div aria-live="polite" aria-atomic="true" class="sr-only">
<span id="page-title-announce"></span>
</div>
<script>
document.addEventListener('astro:after-swap', () => {
const titleElement = document.getElementById('page-title-announce');
if (titleElement) {
titleElement.textContent = `${document.title} に移動しました`;
}
});
</script>
フォールバック戦略とブラウザ対応
View Transitions API は比較的新しい API のため、ブラウザ対応状況を確認する必要があります。
2026年5月時点のブラウザ対応状況
| ブラウザ | バージョン | 対応状況 |
|---|---|---|
| Chrome / Edge | 111+ | 完全対応 |
| Safari | 17.4+ | 完全対応(iOS 17.4+) |
| Firefox | 126+ | 実験的サポート(about:config で有効化) |
Astro は View Transitions API が非対応のブラウザでは、自動的に通常の MPA ナビゲーションにフォールバックします。追加のコードは不要です。
フォールバック時の動作確認
開発者ツールで View Transitions を無効化して、フォールバック時の動作を確認できます。
// ブラウザコンソールで実行
document.startViewTransition = undefined;
実プロジェクトでの活用事例
ブログサイトでの実装例
記事一覧から詳細ページへの遷移で、サムネイル画像を維持しながらスムーズに拡大する実装です。
---
// src/pages/blog/index.astro
const posts = await getPosts();
---
<BaseLayout>
<h1>ブログ記事一覧</h1>
<div class="grid grid-cols-3 gap-6">
{posts.map(post => (
<article>
<a href={`/blog/${post.slug}`} data-astro-prefetch="viewport">
<img
src={post.thumbnail}
alt={post.title}
transition:name={`hero-${post.slug}`}
class="rounded-lg shadow-md"
/>
<h2 class="mt-4 text-xl font-bold">{post.title}</h2>
<p class="text-gray-600">{post.excerpt}</p>
</a>
</article>
))}
</div>
</BaseLayout>
詳細ページ側でも同じ transition:name を指定することで、画像がモーフィングします。
---
// src/pages/blog/[slug].astro
const { slug } = Astro.params;
const post = await getPost(slug);
---
<BaseLayout>
<article>
<img
src={post.thumbnail}
alt={post.title}
transition:name={`hero-${slug}`}
class="w-full h-96 object-cover rounded-lg"
/>
<h1 class="text-4xl font-bold mt-8">{post.title}</h1>
<div class="prose prose-lg mt-6" set:html={post.content} />
</article>
</BaseLayout>
EC サイトでの実装例
商品一覧から商品詳細への遷移で、商品画像とカート状態を維持します。
---
// src/components/Cart.astro
---
<div
transition:persist="shopping-cart"
class="fixed top-4 right-4 bg-white p-4 rounded shadow"
>
<span id="cart-count">0</span> 点
</div>
カートアイコンは transition:persist により、ページ遷移後も状態が保持されます。
まとめ
Astro 5.0 の View Transitions を活用することで、以下のメリットが得られます。
- MPA の SEO メリットを保ちながら SPA 風の UX を実現
- 共通要素の状態維持により、音楽プレイヤーやカートなどが途切れない
- transition:name によるモーフィングアニメーションで自然な画面遷移
- プリフェッチによる体感速度の向上
- アクセシビリティへの配慮が標準で組み込まれている
View Transitions は、現代の Web サイトにおいて「SEO」と「UX」のトレードオフを解消する強力な技術です。Astro 5.0 では、この API を非常にシンプルに扱えるため、プロダクションでの採用ハードルが大きく下がりました。
今後、View Transitions API のブラウザ対応が進むにつれ、MPA の標準的な実装パターンとして定着していくでしょう。