CSS REFERENCE

インタラクティブ

view-transition-name 要素

ー ページ遷移や要素の変化を、映画のようなモーフィングアニメーションで演出するAPI

POINT !

view-transition-name 要素のポイント!

  • view-transition-name は View Transitions API を CSS 側で制御するためのプロパティ。同じ名前を「遷移前」と「遷移後」の要素に付けることで、ブラウザが自動的に「この要素が変化した」と認識し、位置・サイズ・形状のモーフィングアニメーションを生成する。
  • 値は CSS の <custom-ident> 形式(--で始まらない任意の名前)。ページ内でユニークである必要があり、同一ページ内で同じ名前を複数要素に付けてはいけない。重複するとアニメーションが壊れる。
  • CSS のみで使える「同一文書内のView Transition」(Chrome 111以降)と、JavaScript の document.startViewTransition() が必要な「クロスドキュメントのView Transition(ページ遷移)」の2種類がある。2025年時点でクロスドキュメント版は Chrome 126以降でサポート。
  • ::view-transition-old(name) と ::view-transition-new(name) の疑似要素に CSS アニメーションを適用することで、デフォルトのクロスフェード以外のカスタムトランジションを定義できる。

概要

view-transition-name は、ブラウザネイティブの View Transitions API をトリガーするためのプロパティです。2つの状態間(画面遷移前後、要素の表示/非表示など)で、まるでネイティブアプリのような滑らかな「モーフィングアニメーション」を、JavaScript をほとんど書かずに実現できます。

【仕組み】
① document.startViewTransition() が呼ばれると(または @view-transition at-rule で自動化されると)、ブラウザは現在の画面を静止画(スナップショット)として保持します。
② DOMを新しい状態に更新します。
③ ブラウザは「古いスナップショット」から「新しい画面」へのアニメーションを自動生成します。
④ view-transition-name が付いた要素は、古い位置から新しい位置へとモーフィングします。

【2種類のView Transition】
・同一文書内(Same-document):SPA での画面切り替え、要素の表示/非表示など。document.startViewTransition() が必要。
・クロスドキュメント(Cross-document):通常のページ遷移(aタグでの画面遷移)をアニメーション化。@view-transition { navigation: auto; } のみで有効化できる(Chrome 126以降)。

従来は FLIP テクニックや複雑なJSライブラリで実装していた演出が、数行のCSSで実現できる革命的な機能です。

具体的な役割

画像ギャラリーからの詳細画面への「ヒーロートランジション」、リスト→詳細ページ遷移のモーフィング、SPA のルート切り替えアニメーション、カードがモーダルへ展開する演出など。

アクセシビリティ

♿ View Transitions のアニメーションも prefers-reduced-motion の対応が必要です。

デフォルトのView Transitionは比較的穏やかなクロスフェードですが、カスタマイズした大きな動きのアニメーションは前庭障害のあるユーザーへの影響があります。

推奨する対応パターン:
@media (prefers-reduced-motion: reduce) {
::view-transition-old(root),
::view-transition-new(root) {
animation: none;
}
}

また、クロスドキュメントのView Transitionは、ページ遷移が完了するまでコンテンツの読み上げが遅延する可能性があります。アニメーションの duration は 300ms 以内を目安にし、ユーザーをあまり待たせないよう配慮してください。

セットで使うプロパティ

📦 view-transition-name を設定した要素は、View Transition 発動時に独立した「スナップショットレイヤー」として扱われます。

【ユニーク性の制約】
同一ページ内で同じ view-transition-name 値を複数の要素が持つことはできません。重複すると、その名前のトランジションは実行されなくなります。
動的にリスト表示される要素(カードリストなど)は、JavaScript で動的に view-transition-name を割り当てる必要があります。

【疑似要素によるカスタマイズ】
::view-transition-old(name):遷移前のスナップショットに適用するスタイル
::view-transition-new(name):遷移後のスナップショットに適用するスタイル
::view-transition-group(name):両スナップショットを包むラッパー

これらに @keyframes を適用することで、デフォルトのクロスフェード以外の演出が可能です。

技術の変遷:昔の常識 vs 今の常識

TRADITION (昔)
ページ遷移アニメーションは SPA フレームワーク(React Router の Transition、Nuxt のページトランジション)や、FLIP(First, Last, Invert, Play)テクニックを JavaScript で実装することで実現していた。実装コストが高く、位置・サイズの計算ミスによるバグも多かった。
MODERN (今)
View Transitions API(Chrome 111以降)により、document.startViewTransition() + view-transition-name の CSS 数行で、ネイティブアプリ品質のページ遷移アニメーションが実現できる。クロスドキュメント版(Chrome 126以降)では @view-transition { navigation: auto; } だけで、通常のマルチページサイトでもアニメーションが付く。

関連する値

値 / 関連 説明
none(初期値) View Transition の対象外。通常の要素はすべてこの値
root ページ全体のルートトランジション。::view-transition-old(root) でページ全体の遷移アニメーションをカスタムできる
<custom-ident> 任意の名前(例: hero-image, nav-bar)。同一ページ内でユニークである必要がある。ハイフン区切りの英数字が慣習
auto Chrome 125以降でサポート。要素の id を元に自動でユニークな名前を生成する(実験的)
ブラウザ対応(同一文書) Chrome 111以降・Edge 111以降でサポート。Firefox・Safariは2025年時点で未対応
ブラウザ対応(クロスドキュメント) Chrome 126以降・Edge 126以降。@view-transition { navigation: auto; } で有効化
継承 なし

利用例

クロスドキュメント View Transition(MPA対応)

マルチページサイトの通常リンク遷移にアニメーションを付ける最もシンプルな実装。各ページに2行のCSSを書くだけ。

HTML Structure
<style>.vt-demo{font-family:sans-serif;background:#f8fafc;border-radius:12px;padding:24px}.vt-card{background:white;border-radius:10px;overflow:hidden;box-shadow:0 2px 12px rgba(0,0,0,0.08);display:flex;flex-direction:column;max-width:280px}.vt-img{height:140px;background:linear-gradient(135deg,#1a56db,#7c3aed);display:flex;align-items:center;justify-content:center;font-size:48px}.vt-body{padding:16px}.vt-title{font-weight:700;font-size:15px;margin-bottom:6px}.vt-desc{font-size:12px;color:#94a3b8;line-height:1.5}.vt-badge{display:inline-block;margin-top:10px;background:#e8f0fd;color:#1a56db;font-size:11px;font-weight:700;padding:3px 10px;border-radius:20px}</style><div class="vt-demo"><p style="font-size:12px;color:#64748b;margin-bottom:16px">👆 view-transition-name: hero-photo が付いた要素</p><div class="vt-card"><div class="vt-img">🖼️</div><div class="vt-body"><div class="vt-title">ヒーロー画像</div><div class="vt-desc">ページ遷移時にこの画像が新しい位置へとモーフィングします</div><div class="vt-badge">view-transition-name: hero-photo</div></div></div></div>
CSS Style
/* すべてのページの CSS に追加 */
@view-transition {
  navigation: auto; /* リンク遷移を自動でView Transitionに */
}

/* ヒーロー画像に名前を付ける */
.hero-image {
  view-transition-name: hero-photo;
}

/* カスタムアニメーション(任意) */
::view-transition-old(hero-photo) {
  animation: 300ms ease-out fade-out;
}
::view-transition-new(hero-photo) {
  animation: 300ms ease-in fade-in;
}

/* 動き低減の配慮 */
@media (prefers-reduced-motion: reduce) {
  ::view-transition-old(root),
  ::view-transition-new(root) {
    animation: none;
  }
}

SPA でのカード → 詳細画面トランジション

JavaScript の document.startViewTransition() を使い、クリックしたカードが詳細ビューへ展開するモーフィングを実装する例。

HTML Structure
<div style="font-family:sans-serif;background:#f8fafc;border-radius:12px;padding:24px"><div style="background:#fef9ec;border:1px solid #fbbf24;border-radius:8px;padding:14px 16px;font-size:13px;color:#92400e;margin-bottom:16px">⚠️ この例はChrome 111以降でのみ動作します。document.startViewTransition() が必要です。</div><div style="display:grid;grid-template-columns:1fr 1fr;gap:12px"><div style="background:linear-gradient(135deg,#1a56db,#0891b2);border-radius:10px;padding:20px;color:white;cursor:pointer;font-size:13px;font-weight:700">カードA<br><span style="opacity:0.7;font-weight:400">クリックで詳細へ</span></div><div style="background:linear-gradient(135deg,#7c3aed,#dc2626);border-radius:10px;padding:20px;color:white;cursor:pointer;font-size:13px;font-weight:700">カードB<br><span style="opacity:0.7;font-weight:400">モーフィングで遷移</span></div></div><p style="margin-top:14px;font-size:12px;color:#64748b">各カードに view-transition-name を動的に付与し、詳細ビューの対応要素と紐付けることでモーフィングが発生します。</p></div>
CSS Style
/* カード一覧のスタイル */
.card {
  /* カードごとにユニークな名前を動的に設定 */
  /* JS側で: card.style.viewTransitionName = `card-${id}` */
}

/* 詳細ページの対応要素にも同じ名前を設定 */
.detail-hero {
  /* card.style.viewTransitionName = `card-${id}` */
}

/* JavaScript側の実装 */
/*
async function navigateToDetail(id) {
  // カードに名前を付ける
  const card = document.querySelector(`[data-id='${id}']`);
  card.style.viewTransitionName = 'active-card';

  await document.startViewTransition(() => {
    // 詳細ビューを表示するDOM更新
    showDetailView(id);
    // 詳細ビューの対応要素にも同じ名前を付ける
    detailHero.style.viewTransitionName = 'active-card';
  }).finished;

  // トランジション完了後は名前をリセット
  card.style.viewTransitionName = '';
}
*/

/* 詳細ビューへの入場アニメーションをカスタム */
::view-transition-new(active-card) {
  animation: 400ms cubic-bezier(0.22, 1, 0.36, 1) expand-in;
}

@keyframes expand-in {
  from {
    clip-path: inset(0 0 0 0 round 12px);
  }
  to {
    clip-path: inset(0 0 0 0 round 0px);
  }
}

よくある誤用・注意点

同一ページ内で同じ view-transition-name を複数の要素に付けるのは最も多い誤り。リスト表示など動的に生成される要素には、必ず id などを使ってユニークな名前を割り当てる。また、ブラウザ対応を無視して本番使用するのも危険。

HTML Structure
CSS (Incorrect)
/* ❌ 悪い例:同じ名前を複数要素に付けている */
.card-1 { view-transition-name: card; } /* 重複! */
.card-2 { view-transition-name: card; } /* 重複! */
/* → 同ページに同名が複数あるとトランジションが無効になる */

/* ❌ 悪い例:すべての要素に同じ名前 */
.list-item {
  view-transition-name: item; /* 全アイテムに同じ名前 → 壊れる */
}

/* ✅ 良い例:動的にユニークな名前を付ける */
/* HTML: <div class="card" style="view-transition-name: card-1"> */
/* JS:   card.style.viewTransitionName = `card-${item.id}`; */

/* ✅ 良い例:@supports でフォールバック */
@supports not (view-transition-name: none) {
  /* 未対応ブラウザ向けのフォールバックスタイル */
}