「CSS View Transitions API 実践ガイド」ページ遷移とUI変化に滑らかなアニメをつける

たった数行のCSSで、DOMの変化やページ遷移を映画のワンカットのように繋げる。長年JSで頑張ってきた領域が、ついにCSS標準で扱える時代に入りました。

「DOM変化を滑らかに繋ぎたい」その願いが、CSS標準になった

カードをクリックして詳細ページに飛ぶとき、サムネイル画像がスッと拡大されながら遷移する。Instagramや最近のスマホアプリでよく見るあの動き、Webでやろうとすると結構しんどかったんです。

FLIP(First, Last, Invert, Play)テクニックでJSをゴリゴリ書いたり、Framer MotionのlayoutIdに頼ったり。実装コストが高く、フレームワーク依存で、しかも要素のサイズ計算がズレるとガタつく。3年前にECサイトのカード遷移アニメを実装したときは、PCとスマホで挙動を合わせるだけで2日溶けました。正直、しんどい。

これを根本から変えるのが View Transitions API。Chrome 111で同一ドキュメント版が、Chrome 126でクロスドキュメント版(MPA対応)が入り、2025年にはSafari 18.2やFirefoxも追従。ようやく「実務で使える」段階に来ました。

📌 何ができるのか
DOMが変わる前後のスナップショットをブラウザが自動で取り、両者を補間してアニメーションしてくれます。書き手は「どう動かすか」だけCSSで指示すればいい。状態管理もFLIPの計算もブラウザ任せ。

最小構成は、たった2行

まずは一番シンプルな例から。状態を切り替えるとき、いつもならclassList.toggle()するだけのコードを、document.startViewTransition()で包む。それだけです。

最小構成のView Transition
/* CSS:アニメーションさせたい要素に名前をつける */
.box {
  view-transition-name: my-box;
}
JS:DOM変更をstartViewTransitionで包むだけ
button.addEventListener('click', () => {
  // 対応していないブラウザのフォールバック */
  if (!document.startViewTransition) {
    box.classList.toggle('is-large');
    return;
  }
  document.startViewTransition(() => {
    box.classList.toggle('is-large');
  });
});

これだけで、サイズも色も角丸も、全部のプロパティ変化を補間してくれる。view-transition-nameを付けた要素は「この要素は前後で同一だよ」とブラウザに伝える役割を持ちます。同じ名前があれば、ブラウザがその間を繋いでくれる仕組み。

▶ Live Demo — ボタンを押すとサイズも色も滑らかに変化
⚠️ 注意
view-transition-name同時に同じ名前の要素が2つ以上存在してはいけません。リストの全アイテムに同じ名前を付けるとエラーで止まります。各要素にユニークな名前を振るのが鉄則。

リストの並び替えに使う、現場で一番役立つパターン

個人的に「これが一番ありがたい」と思っているのが、リストアイテムの並び替えアニメ。TODOアプリの優先度変更、商品リストの並び替え、ランキングの順位変動。今まではFLIPを実装するか、react-flip-toolkitのようなライブラリに頼るしかなかった領域です。

各アイテムにユニークな名前を振る
.list-item[data-id="1"] { view-transition-name: item-1; }
.list-item[data-id="2"] { view-transition-name: item-2; }
/* ...以下、IDごとに */
JS:並び替えをトランジションで包むだけ
shuffleBtn.addEventListener('click', () => {
  document.startViewTransition(() => {
    // DOMの並び替え処理(Array.sortでもReact再レンダーでもOK) */
    const items = [...list.children];
    items.sort(() => Math.random() - 0.5);
    items.forEach(item => list.appendChild(item));
  });
});

動かしてみてください。アイテムがフワッと位置を入れ替えるのが分かるはずです。書いたJSは並び替えロジックだけ。アニメーションのコードは一行も書いていない。これが効きます。

▶ Live Demo — シャッフルボタンで順番がアニメ付きで入れ替わる
1朝のコーヒー
2メール返信
3記事執筆
4夕方の散歩

カードを画面いっぱいに開く「ヒーロー遷移」

ECサイトの商品カードや、ブログの記事カード。クリックすると「カードそのものがスッと拡大して詳細表示になる」演出、おそらく一番需要があるパターンです。

ポイントは、カードの中の要素(タイトル、画像)にも別々のview-transition-nameを付けること。タイトルならcard-title、画像ならcard-imageのように。そうすると、それぞれが「前後で同一の要素」として補間されます。

❌ やりがちなNG
.card {
  view-transition-name: card;
}
/* 中の要素には何もつけない */
/* → カード全体はフェードで補間されるが、 */
/*   中のタイトルや画像はカクッと表示が切り替わる */
✅ 正しい書き方
.card {
  view-transition-name: card;
}
.card-title {
  view-transition-name: card-title;
}
.card-image {
  view-transition-name: card-image;
}
/* 中の要素も個別に補間されて、文字サイズや画像位置が */
/* 滑らかに繋がる */
▶ Live Demo — カードをクリックで拡大、もう一度で元に戻る

View Transitions入門

カードのサイズも、タイトルの文字サイズも、角丸の半径も、全部CSSが補間してくれます。クリックして試してみてください。

アニメーションを自分好みにカスタマイズする

デフォルトはクロスフェード(不透明度の補間)です。これだけでも十分使えますが、スライドにしたい、もっと速くしたい、というときは::view-transition-old()::view-transition-new()の擬似要素を上書きします。

アニメーションの速度と動きを変える
/* デフォルトのフェードを「右からスライドイン」に変える */
@keyframes slide-in {
  from { transform: translateX(30px); opacity: 0; }
}
@keyframes slide-out {
  to { transform: translateX(-30px); opacity: 0; }
}

::view-transition-old(card) {
  animation: 0.3s ease-out slide-out;
}
::view-transition-new(card) {
  animation: 0.3s ease-out slide-in;
}

名前を(*)にすると全要素に一括適用できます。サイト全体のページ遷移を一括で「フェード0.2秒に統一」みたいな使い方も簡単。

💡 アクセシビリティ配慮
動きが苦手なユーザー向けに @media (prefers-reduced-motion: reduce)animation-duration: 0.01s にしておくこと。これを忘れて怒られた経験あり。

MPA(普通のページ遷移)でも使える時代に

2024年中盤までは「同一ドキュメント内のDOM変化」にしか使えませんでした。SPAじゃないと意味がない、と。それが変わったのがChrome 126で入ったCross-document View Transitionsです。普通の<a>タグでの遷移にも適用できる。

MPAでView Transitionsを有効にする
/* 各ページのCSSに、これを書くだけ */
@view-transition {
  navigation: auto;
}

/* 遷移前後で共通の要素(ヘッダーロゴなど)に名前を付ける */
.site-logo {
  view-transition-name: logo;
}

これで通常のリンククリックの遷移にもアニメが付きます。Astroで構築したコーポレートサイトに導入したことがありますが、JSをほぼ書かずにNext.jsアプリのような遷移体験が作れて、これは正直、感動しました。

⚠️ ブラウザ対応の現実
SPA向けの基本機能はChrome / Edge / Safari 18.2+ で利用可能。Firefoxは2025年内に対応見込み。MPA向けのクロスドキュメント版はまだChromium系がメイン。if (!document.startViewTransition) でのフォールバックは必須です。

まとめ

  • View Transitions APIは、DOM変化の前後をブラウザが自動補間してくれる新機能で、FLIPやFramer Motionに頼らずに滑らかな遷移を実装できる。
  • 使い方はdocument.startViewTransition(() => { /* DOM変更 */ })で包むだけ。CSSでview-transition-nameを付ければ要素が補間対象になる。
  • 同じview-transition-nameを同時に2つ以上持てない。リストでは各アイテムにユニークな名前を振ること。
  • カードの拡大遷移では、親だけでなく中のタイトルや画像にも個別に名前を付けると、文字サイズや位置まで滑らかに繋がる。
  • アニメーションの動きや速度は::view-transition-old()::view-transition-new()の擬似要素で自由にカスタマイズできる。
  • Chrome 126以降、通常のページ遷移(MPA)にも@view-transition { navigation: auto }で適用可能になり、Astroや静的サイトでも使える時代になった。
  • prefers-reduced-motionへの配慮と、非対応ブラウザへのフォールバック分岐は忘れずに。