UIが遷移するアニメーションを簡単にするView Transition API
View Transition APIがBaseline 2025に追加され、Web上のUI遷移を簡単にアニメーション化可能になりました。異なるページ間の遷移や同一ページ内のDOM更新時に、要素の位置やスタイルの変化をアニメーション化できます。CSSによるスタイル制御も豊富に用意されており、柔軟なカスタマイズが可能です。
はじめに
Web上のさまざまなUIの遷移を簡単にアニメーション化するView Transition APIがBaseline 2025に追加されました。
異なるDocument間(同一のオリジン)の遷移や、同一Document内のDOM更新時に、要素の位置やスタイルの変化に対するアニメーションを付与します。
例として、当サイトではブログの一覧とブログ記事の遷移で、View Transition APIを利用したアニメーションを採用しています(ReactのViewTransitionコンポーネントを使っているので間接的な利用ではあります)。
記事のタイトルや、タグ、作成・更新日時の位置が変化するアニメーションを確認できるかと思います。
この記事では、そんなView Transition APIについて紹介します。この記事ではView Transition APIによって発生するアニメーションのことを「遷移アニメーション」と呼びます。
異なるDocument間の遷移アニメーション
異なるDocument間の遷移アニメーションは同一のオリジン間でのみ適用できます。
さらに、両者がそれぞれ読み込むCSSでView Transitionを@view-transitionを用いて有効にする必要があります(Firefoxは@view-transition未対応)。
@view-transition {
navigation: auto;
}
view-transition-nameに同一の値を付与することで、遷移前の古いページと遷移後の新しいページの要素が対応付けられ、アニメーションが適用されます。
デフォルトでは、:rootにview-transition-name: root;が付与されており、特別な指定がない場合は画面全体に対してアニメーションが適用されます。
同一Document内の遷移アニメーション
同一Document内のDOM更新に対して遷移アニメーションを適用する時はstartViewTransitionを使用します。
startViewTransitionはDocumentオブジェクトのメソッドとして実装されており、呼び出しに応じてViewTransitionオブジェクトを返します。
引数にはupdateCallbackという、遷移アニメーションの対象となるDOMの更新を行う関数を渡します。
document.startViewTransition(() => {
// DOMの更新処理
updateViewTransitionTargetDom();
});
また、オプションとして、オブジェクト、updateとtypesを指定することができます。
updateはupdateCallbackと同じものを指しており、typesは遷移アニメーションに対するクラス名や識別子を指定できます。これによって、遷移アニメーションのスタイルをカスタマイズできます。
document.startViewTransition({
update: () => {
// DOMの更新処理
updateViewTransitionTargetDom();
},
types: ['custom-transition']
});
ViewTransitionオブジェクトはfinished、ready、updateCallbackDoneという3つのプロミスをプロパティに持っています。
const transition = document.startViewTransition(() =>
updateTheDOMSomehow(data),
);
// 遷移アニメーションが完了したら解決する
transition.finished.then(() => {
// ...
});
// 遷移アニメーションが開始する直前に解決する
transition.ready.then(() => {
// ...
});
// DOMの更新処理が完了したら解決する
transition.updateCallbackDone.then(() => {
// ...
});
また、遷移アニメーションをスキップするskipTransitionメソッドも持ちます。
const transition = document.startViewTransition(() =>
updateTheDOMSomehow(data),
);
const timeoutId = setTimeout(() => {
// 1秒経ったら遷移アニメーションをスキップする
transition.skipTransition();
}, 1000);
transition.finished.then(() => {
// 完了していたらスキップタイムアウトをクリアする
clearTimeout(timeoutId);
});
関連するCSSプロパティ
view-transition-name
view-transition-nameプロパティは、ある要素に対して特別な遷移アニメーションを適用するための識別子を指定します。
/* デフォルトのUAのスタイル */
:root {
view-transition-name: root;
}
:root {
view-transition-name: none;
}
.article {
view-transition-name: article;
}
.tag-list {
view-transition-name: tag-list;
}
遷移の前後に同一のview-transition-nameを持つ要素が存在する場合、それらの要素間で遷移アニメーションが適用されます。
view-transition-nameにnoneを指定した場合のみ、指定した要素が遷移アニメーションの対象から除外されます。
一つの画面に同一のview-transition-nameがある場合、その遷移アニメーションはスキップされます。
view-transition-class
view-transition-classは後に紹介する::view-transition-groupやview-transition-image-pair疑似要素等を用いた遷移アニメーションのスタイルをまとめて適用するためのプロパティです。
.tag {
view-transition-name: tag-1;
view-transition-class: tag-transition;
}
::view-transition-group(.tag-transition) {
animation-duration: 0.5s;
}
:active-view-transition
:active-view-transition疑似クラスは、現在進行中の遷移アニメーションに対してスタイルを適用するために使用されます。
/* 遷移中の時はbuttonが無効であることを伝わるように薄く表示する */
.transition-button:active-view-transition {
opacity: 0.8;
}
::view-transition
::view-transition疑似要素は、遷移アニメーション全体のOverlayに対するスタイルを付与できます。
遷移アニメーション中は最上位レイヤーにビューポート全体を覆うコンテナが存在し(<dialog>要素のoverlayのような感じ?)、それに対するスタイルを適用することができます。
/* デフォルトのUAのスタイル */
:root::view-transition {
position: absolute;
inset: 0;
}
::view-transition {
/* トランジション中は半透明にする */
background-color: rgba(0, 0, 0, 0.5);
}
::view-transition-group
::view-transition-group擬似要素は、特定の遷移アニメーションに対するスタイルを付与できる::view-transitionです。::view-transitionとは親と子の関係にあります。
スタイルの適用には、view-transition-nameやview-transition-classで指定した値や、それらが割り当てられていない遷移アニメーションに割り当てられるroot、全ての遷移アニメーションに対する*を用います。
/* デフォルトのUAのスタイル */
:root::view-transition-group(*) {
position: absolute;
top: 0;
left: 0;
animation-duration: 0.25s;
animation-fill-mode: both;
}
::view-transition-group(root) {
/* 特別な割り当てがないものに対するスタイル */
}
::view-transition-group(card1) {
/* view-transition-nameでcard1を付与されたものに対するスタイル */
}
::view-transition-group(.card) {
/* view-transition-classでcardを付与されたものに対するスタイル */
}
::view-transition-image-pair
::view-transition-image-pair疑似要素は、遷移アニメーションの前後の要素に対してスタイルを適用するために使用されます。::view-transition-groupとは親と子の関係にあります。
スタイルの適用方法は::view-transition-groupと同様に、view-transition-nameやview-transition-classで指定した値や、それらが割り当てられていない遷移アニメーションに割り当てられるroot、全ての遷移アニメーションに対する*を用います。
/* デフォルトのUAのスタイルを合成したもの */
:root::view-transition-image-pair(*) {
position: absolute;
inset: 0;
animation-duration: inherit;
animation-fill-mode: inherit;
animation-delay: inherit;
animation-timing-function: inherit;
animation-iteration-count: inherit;
animation-direction: inherit;
animation-play-state: inherit;
}
::view-transition-newと::view-transition-old
::view-transition-new疑似要素と::view-transition-old疑似要素は、遷移アニメーションの新しい要素と古い要素に対してスタイルを適用するために使用されます。これらは::view-transition-image-pairの子要素です。
/* デフォルトのUAのスタイルを合成したもの */
:root::view-transition-old(*),
:root::view-transition-new(*) {
position: absolute;
inset-block-start: 0;
inline-size: 100%;
block-size: auto;
animation-duration: inherit;
animation-fill-mode: inherit;
animation-delay: inherit;
animation-timing-function: inherit;
animation-iteration-count: inherit;
animation-direction: inherit;
animation-play-state: inherit;
}
/* Default cross-fade transition */
@keyframes -ua-view-transition-fade-out {
to { opacity: 0; }
}
@keyframes -ua-view-transition-fade-in {
from { opacity: 0; }
}
/* Keyframes for blending when there are 2 images */
@keyframes -ua-mix-blend-mode-plus-lighter {
from { mix-blend-mode: plus-lighter }
to { mix-blend-mode: plus-lighter }
}
例
startViewTransitionを使ったDOMの更新アニメーションの例です。
View Transition基本デモ
- アイテム 1
- アイテム 2
- アイテム 3
- アイテム 4
- View TransitionのON/OFFの切り替えは
view-transition-nameをnoneに指定することで行なっています。 - View TransitionがONの時は、アイテム番号ごとの
view-transition-nameを持ちます(例:item-1)。 - 各アイテムは、まとまったスタイルを付与するために
view-transition-class: item;を持ちます。
::view-transition-group(.item) {
border-radius: var(--radius-md);
}
::view-transition-group(item-1) {
background-color: var(--red-800);
}
::view-transition-image-pair(item-2) {
background-color: var(--pink-800);
}
::view-transition-old(item-3) {
background-color: var(--purple-800);
}
::view-transition-new(item-4) {
background-color: var(--cyan-800);
}各擬似要素がどのような役割でどのようにスタイルが適用されているがなんとなくわかると思います。
おわりに
View Transition APIは、Webアプリケーションに滑らかで自然な遷移アニメーションを簡単に実装できる強力なAPIです。
このAPIによるアニメーションは同一Document内のDOM更新だけではなく、異なるDocument間の遷移にも対応しているため、幅広いユースケースで活用できます。
CSSのview-transition-nameやview-transition-classを使った要素の対応付け、::view-transitionなどの疑似要素による細かなスタイル制御など、柔軟なカスタマイズが可能な点も魅力です。
ReactなどのUIライブラリにも専用のコンポーネント<ViewTransition>が組み込まれていたり、使いやすい状況になっているため、ぜひ活用してみてください。