「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も追従。ようやく「実務で使える」段階に来ました。
最小構成は、たった2行
まずは一番シンプルな例から。状態を切り替えるとき、いつもならclassList.toggle()するだけのコードを、document.startViewTransition()で包む。それだけです。
/* CSS:アニメーションさせたい要素に名前をつける */
.box {
view-transition-name: my-box;
}
button.addEventListener('click', () => {
// 対応していないブラウザのフォールバック */
if (!document.startViewTransition) {
box.classList.toggle('is-large');
return;
}
document.startViewTransition(() => {
box.classList.toggle('is-large');
});
});
これだけで、サイズも色も角丸も、全部のプロパティ変化を補間してくれる。view-transition-nameを付けた要素は「この要素は前後で同一だよ」とブラウザに伝える役割を持ちます。同じ名前があれば、ブラウザがその間を繋いでくれる仕組み。
リストの並び替えに使う、現場で一番役立つパターン
個人的に「これが一番ありがたい」と思っているのが、リストアイテムの並び替えアニメ。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ごとに */
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は並び替えロジックだけ。アニメーションのコードは一行も書いていない。これが効きます。
カードを画面いっぱいに開く「ヒーロー遷移」
ECサイトの商品カードや、ブログの記事カード。クリックすると「カードそのものがスッと拡大して詳細表示になる」演出、おそらく一番需要があるパターンです。
ポイントは、カードの中の要素(タイトル、画像)にも別々のview-transition-nameを付けること。タイトルならcard-title、画像ならcard-imageのように。そうすると、それぞれが「前後で同一の要素」として補間されます。
.card {
view-transition-name: card;
}
/* 中の要素には何もつけない */
/* → カード全体はフェードで補間されるが、 */
/* 中のタイトルや画像はカクッと表示が切り替わる */
.card {
view-transition-name: card;
}
.card-title {
view-transition-name: card-title;
}
.card-image {
view-transition-name: card-image;
}
/* 中の要素も個別に補間されて、文字サイズや画像位置が */
/* 滑らかに繋がる */
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秒に統一」みたいな使い方も簡単。
MPA(普通のページ遷移)でも使える時代に
2024年中盤までは「同一ドキュメント内のDOM変化」にしか使えませんでした。SPAじゃないと意味がない、と。それが変わったのがChrome 126で入ったCross-document View Transitionsです。普通の<a>タグでの遷移にも適用できる。
/* 各ページのCSSに、これを書くだけ */
@view-transition {
navigation: auto;
}
/* 遷移前後で共通の要素(ヘッダーロゴなど)に名前を付ける */
.site-logo {
view-transition-name: logo;
}
これで通常のリンククリックの遷移にもアニメが付きます。Astroで構築したコーポレートサイトに導入したことがありますが、JSをほぼ書かずにNext.jsアプリのような遷移体験が作れて、これは正直、感動しました。
まとめ
- 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への配慮と、非対応ブラウザへのフォールバック分岐は忘れずに。