はじめに
ページ遷移やUI切り替えに少し動きを足したいけれど、場面ごとにアニメーションを分岐させるのが面倒、ということはよくあります。前へ進むときと戻るときで動きを変えたい、モーダルを開くときだけ軽く拡大したい、といった要望は定番です。
View Transitions APIは以前から便利でしたが、2026年1月にMDNでViewTransition.typesがBaseline 2026として整理され、遷移の種類を扱う書き味がかなり分かりやすくなりました。document.startViewTransition()でDOM更新を包みつつ、typesで「この遷移はforward」「これはmodal」と名前を付けてCSS側で演出を切り替えられます。
この記事では、同一ページ内のUI切り替えを例に、まずは基本の使い方を押さえたうえで、実務でよくある「進む・戻る」とprefers-reduced-motionを考慮した実装までつなげます。
機能やライブラリの概要
View Transitions APIは、DOM更新の前後をブラウザにキャプチャさせて、その差分を自然につなぐためのWeb標準APIです。単純なクロスフェードだけでも便利ですが、最近は「どの遷移なのか」をtypesで表現できるようになり、同じ更新処理でも文脈に応じてアニメーションを変えやすくなりました。
MDNのViewTransition関連ドキュメントでは、ViewTransition自体はBaseline 2025、typesプロパティはBaseline 2026として案内されています。つまり、最新環境では「遷移オブジェクトを受け取り、あとから種類を足す」という使い方がかなり現実的になってきた、という見方ができます。
実務で覚えておくと便利なのは次の3点です。
document.startViewTransition()でDOM更新をひとまとまりにするtypes配列、またはvt.types.add()で遷移に名前を付ける:active-view-transition-type()でCSS側の演出を出し分ける
これが揃うと、「処理は同じだが見せ方だけ変えたい」場面に強くなります。
基本の使い方
最初はタブ風のUIで試すのが分かりやすいです。このコードでは、パネルの中身を切り替えるときにView Transitionを開始し、detailsという種類名を付けています。
<div class="panel-switcher">
<div class="actions">
<button type="button" data-view="overview">概要</button>
<button type="button" data-view="details">詳細</button>
</div>
<section class="panel" data-panel>
<h2>概要</h2>
<p>この製品の特徴を短くまとめています。</p>
</section>
</div>const panel = document.querySelector("[data-panel]");
const buttons = document.querySelectorAll("[data-view]");
const views = {
overview: {
title: "概要",
body: "この製品の特徴を短くまとめています。",
},
details: {
title: "詳細",
body: "導入条件やサポート範囲、運用時の注意点まで確認できます。",
},
};
for (const button of buttons) {
button.addEventListener("click", () => {
const nextView = views[button.dataset.view];
if (!document.startViewTransition) {
renderPanel(nextView);
return;
}
document.startViewTransition({
update() {
renderPanel(nextView);
},
types: ["details"],
});
});
}
function renderPanel(view) {
panel.innerHTML = `
<h2>${view.title}</h2>
<p>${view.body}</p>
`;
}.panel {
view-transition-name: panel;
}
html:active-view-transition-type(details)::view-transition-old(panel) {
animation: panel-fade-out 180ms ease both;
}
html:active-view-transition-type(details)::view-transition-new(panel) {
animation: panel-rise-in 220ms ease both;
}
@keyframes panel-fade-out {
to {
opacity: 0;
transform: translateY(-8px);
}
}
@keyframes panel-rise-in {
from {
opacity: 0;
transform: translateY(12px);
}
}このコードでやっていることは単純で、DOM更新をupdate()にまとめ、typesで遷移の名前を付けているだけです。CSS側ではその名前に反応して、入れ替え方だけを差し替えています。
従来ならクラスの付け替えやタイミング制御をJavaScript側に寄せがちでしたが、View Transitionを使うと「更新処理」と「見せ方」を分けやすくなります。
便利な使いどころ
この機能が効きやすいのは、画面の切り替え自体は単純なのに、見せ方だけ場面ごとに変えたいUIです。
- 商品ギャラリーの「次へ」「前へ」
- フィルター切り替えで一覧を更新するUI
- モーダル、ドロワー、詳細パネルの開閉
- SPAのページ切り替えや小さなルーター実装
特に便利なのは、「forward」「backward」「modal」くらいの少ない語彙を先に決めておけることです。デザイナーと相談するときも、「戻る遷移は右から左ではなく、左から右に戻す」といった話をコードに落としやすくなります。
また、同じ描画関数を使い回しながら演出だけ変えられるので、状態管理のコードを必要以上に複雑にしなくて済みます。アニメーション用のif分岐が描画ロジックに混ざりにくいのは、実務ではかなり大きいです。
応用コード
次は、前後移動で演出を変える例です。このコードでは、押したボタンに応じてforwardかbackwardを付け、同じ画像切り替えでもアニメーションの方向を切り替えています。
<section class="gallery">
<div class="gallery-card" data-card>
<img
src="/images/feature-01.jpg"
alt="展示会ブースのメインビジュアル"
width="960"
height="540"
/>
<p data-caption>展示会ブースのメインビジュアル</p>
</div>
<div class="gallery-nav">
<button type="button" data-dir="backward">前へ</button>
<button type="button" data-dir="forward">次へ</button>
</div>
</section>const items = [
{
src: "/images/feature-01.jpg",
alt: "展示会ブースのメインビジュアル",
},
{
src: "/images/feature-02.jpg",
alt: "ライト演出を使ったキービジュアル",
},
{
src: "/images/feature-03.jpg",
alt: "案内サインを含めた全体レイアウト",
},
];
const card = document.querySelector("[data-card]");
const caption = document.querySelector("[data-caption]");
const reduceMotion = window.matchMedia("(prefers-reduced-motion: reduce)");
let currentIndex = 0;
document.querySelectorAll("[data-dir]").forEach((button) => {
button.addEventListener("click", () => {
const direction = button.dataset.dir;
const delta = direction === "forward" ? 1 : -1;
const nextIndex = (currentIndex + delta + items.length) % items.length;
const nextItem = items[nextIndex];
const update = () => {
const image = card.querySelector("img");
image.src = nextItem.src;
image.alt = nextItem.alt;
caption.textContent = nextItem.alt;
currentIndex = nextIndex;
};
if (!document.startViewTransition || reduceMotion.matches) {
update();
return;
}
const transition = document.startViewTransition({ update });
transition.types.add(direction);
});
});.gallery-card img,
.gallery-card p {
view-transition-name: gallery-content;
}
html:active-view-transition-type(forward)::view-transition-old(gallery-content) {
animation: slide-out-left 240ms ease both;
}
html:active-view-transition-type(forward)::view-transition-new(gallery-content) {
animation: slide-in-right 240ms ease both;
}
html:active-view-transition-type(backward)::view-transition-old(gallery-content) {
animation: slide-out-right 240ms ease both;
}
html:active-view-transition-type(backward)::view-transition-new(gallery-content) {
animation: slide-in-left 240ms ease both;
}
@keyframes slide-out-left {
to {
opacity: 0;
transform: translateX(-24px);
}
}
@keyframes slide-in-right {
from {
opacity: 0;
transform: translateX(24px);
}
}
@keyframes slide-out-right {
to {
opacity: 0;
transform: translateX(24px);
}
}
@keyframes slide-in-left {
from {
opacity: 0;
transform: translateX(-24px);
}
}
@media (prefers-reduced-motion: reduce) {
::view-transition-group(*) {
animation-duration: 1ms;
}
}ここでは、更新処理そのものは1つにまとめつつ、transition.types.add(direction)だけで演出を分岐しています。こうしておくと、将来的にzoomやmodalを足したくなっても、CSSの責務として追加しやすいです。
実務では、商品カルーセル、実績ギャラリー、ケーススタディの前後ページなどでかなり使いやすい形です。特にprefers-reduced-motionを先に見ておけば、演出を入れつつ配慮も崩しにくくなります。
注意点
view-transition-nameを付けすぎない
画面全体に広く付けると、想定外の要素までキャプチャされて管理しづらくなります。最初はカードや画像など、動かしたい要素だけに絞るほうが安全です。typesは少数の語彙に整理する
何でもかんでも別名にすると、CSSの分岐が増えて保守しづらくなります。forward、backward、modalくらいから始めるのが現実的です。- 未対応環境のフォールバックを先に決める
document.startViewTransitionがない環境では、そのまま通常更新に落とすだけでも十分です。アニメーションがないと破綻するUIにはしないほうが安定します。 - MPAでの高度な使い分けは別途検証する
MDNではpageswapやpagerevealを使ったクロスドキュメント遷移の例も案内されていますが、こちらは周辺APIを含めて段階的に試すのがよさそうです。まずは同一ページ内の切り替えで手応えをつかむのがおすすめです。
まとめ
View Transitions APIのよさは、派手なデモよりも「同じ更新処理に、場面ごとの意味を持たせられる」ところにあります。typesが入ることで、前後移動やモーダル表示のような定番パターンを、かなり自然に設計できるようになりました。
まずはギャラリーやタブ、詳細パネルのような小さいUIから試すと導入しやすいです。アニメーションの実装そのものより、更新ロジックと見せ方をきれいに分けられる感触が、現場では効いてきます。
ポイント
typesを使うと、同じDOM更新でもforwardやbackwardなど意味ごとに演出を切り替えやすい- 画像ギャラリーや詳細パネルのような小さなUIから入れると導入しやすい
prefers-reduced-motionと通常更新へのフォールバックを最初からセットで考えると安全