【実務・中級編】 ::view-transition-new 擬似要素による遷移後状態 – CSS実践ガイド

お疲れ。そろそろ「ただ動くだけのCSS」から卒業して、ユーザーの心を掴むリッチな体験を作りたい頃合いだと思ってな。今日は、モダンフロントエンドの最前線でひそかに(いや、盛大に)話題を集めている View Transitions API、その中でも肝となる `::view-transition-new` 擬似要素について徹底的に解説しよう。

現場で「ページ遷移をもっと滑らかにしたい」「SPAみたいなリッチなアニメーションをMPAでも手軽に実装したい」と相談されることが増えたんじゃないか?
従来のCSSアニメーションやJavaScriptライブラリを総動員してヒーヒー言いながら実装していたあの苦労が、この数行のCSSで嘘のように解決する時代が来たんだ。

今回は、中級から一歩抜け出したいキミに向けて、ブラウザの裏側の動きから、実務ですぐに使える実践的なテクニックまで叩き込んでやる。ついてきな。

—

1. そもそも `::view-transition-new` とは何か?(標準仕様とブラウザの裏側の話)

まず前提として、View Transitions API が裏側で何をやっているかを知る必要がある。
ブラウザは、ページ遷移(あるいはDOMの書き換え)が発生した瞬間、古い状態のスクリーンショットと新しい状態のDOMの双方向をキャプチャする。

ここで登場するのが、仮想的なアニメーションコンテナだ。ブラウザは画面全体を一時的に一枚の「画像(スナップショット)」として扱い、次のようなツリー構造の擬似要素を裏で生成する。

::view-transition
├── ::view-transition-group(root)
│ ├── ::view-transition-old(root) <-- 遷移前の状態(古い画面) │ └── ::view-transition-new(root) <-- 遷移後の状態(新しい画面) この構造の中で、`::view-transition-new` は「遷移後の新しい状態(スナップショット、もしくはライブDOM)」をカプセル化する擬似要素だ。
デフォルトの状態では、ブラウザはこの `::view-transition-new` を `opacity: 0` から `opacity: 1` へとふんわりクロスフェードさせる(フェードイン)。

しかし、プロのフロントエンドエンジニアである我々が、ブラウザのデフォルト設定に甘んじる必要はない。この擬似要素に対してCSSアニメーションを明示的に指定してやることで、ただのクロスフェードを、スライド、ズーム、果ては立体的なワイプ演出へと劇的に昇華させることができるんだ。

—

2. 現場で使える!実践的なサンプルコード

理屈はこれくらいにして、実際に手を動かしてみよう。
今回は、実務で最も需要が高い「右からスライドインしてくるダイナミックなページ遷移」のコードだ。

SPA(Single Page Application)のルーター遷移でも、MPA(Multi Page Application)の `document.startViewTransition()` でも、CSS側の作法は全く同じだ。

/ ————————————————————————–

  • View Transitions API 基本設定
  • ————————————————————————– /

フロー全体のアニメーション時間をここで一括コントロールする。
デフォルトは0.25s程度だが、ちょっとリッチに見せるなら0.4s〜0.5sが黄金比だ。
/
::view-transition-old(root),
::view-transition-new(root) {
animation-duration: 0.4s;
animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1); / エージングは気持ちいい「Out Expo」系が鉄則 /
}

/ ————————————————————————–

  • 遷移前(古い画面)の制御: ::view-transition-old
  • ————————————————————————– /

::view-transition-old(root) {
/ 古い画面をその場に固定しつつ、少しずつ暗く(あるいは縮小)していくと奥行きが出る /
animation-name: fade-out;
}

@keyframes fade-out {
from {
opacity: 1;
transform: scale(1);
}
to {
opacity: 0;
transform: scale(0.95); / 奥へ引っ込むような演出 /
}
}

/ ————————————————————————–

  • 遷移後(新しい画面)の制御: ::view-transition-new (本日の主役!)
  • ————————————————————————– /

::view-transition-new(root) {
/ 新しい画面を右側からスライドインさせながら、同時にフェードインさせる /
animation-name: slide-in-from-right;
}

@keyframes slide-in-from-right {
from {
opacity: 0;
transform: translateX(100%); / 画面の右外側からスタート /
}
to {
opacity: 1;
transform: translateX(0); / 定位置に着地 /
}
}

このCSSを一枚噛ませるだけで、ユーザーは「おっ、このサイト、アプリっぽいな!」と感じる滑らかな体験を手に入れることができる。これだけでもう、周りのジュニア層の一歩先を行く仕事ができるはずだ。

—

3. シニアが教える、実務でハマりがちな「落とし穴」とベストプラクティス

さて、ここからが一番大事な話だ。きれいなコードを書くだけならAIでもできるが、「実務の現場で起えうるトラブルをどう回避するか」がシニアの腕の見せ所なんだよ。

① `view-transition-name` の乱用に気をつけろ

要素ごとに個別のトランジションを適用したい場合、`view-transition-name: unique-id;` を各要素(例えばサムネイル画像など)に付与したくなる。
だが、DOM上に同じ `view-transition-name` が同時に複数存在してはならないという厳格な仕様上のルールがある。これをやると、ブラウザがレンダリングエラーを起こしてトランジション自体がサイレントに失敗する。
リスト一覧から詳細ページへ飛ぶような「Shared Element Transition(要素の共有遷移)」を実装するときは、JS側で動的に `view-transition-name` を付与・クリーンアップする設計を徹底しろ。

② 「動きの好み(prefers-reduced-motion)」への配慮を忘れるな

ここ、プロとしてのプライドを持とう。眩暈(めまい)や前庭障害を持つユーザーにとって、激しい画面の移動やズームは苦痛でしかない。Accessibilityの観点からも、モーション軽減の設定をしているユーザーにはアニメーションを必ずオフにすべきだ。

/ ユーザーが「視差効果を減らしたい」設定にしている場合のフォールバック /
@media (prefers-reduced-motion: reduce) {
::view-transition-old(root),
::view-transition-new(root) {
animation: none !important;
}
}

この数行をサボるかサボらないかで、プロダクトの品質、ひいてはエンジニアとしての信頼度が決まる。絶対に忘れないように。

③ アニメーションのパフォーマンス(Compositorの活用)

`::view-transition-new` のアニメーションを定義する際、`transform` と `opacity` 以外のプロパティ(例えば `width` や `height`, `top`, `left` など)を動かそうとしていないか?
これらをアニメーションさせると、ブラウザはレイアウトとペイントを毎フレーム再計算(リフロー)することになり、カクつき(Jank)の原因になる。
`::view-transition-new` 内で動かしていいのは、基本的に `transform` と `opacity` のみ。 これらはGPU(コンポジター・スレッド)で処理されるため、60fpsの滑らかなアニメーションが約束される。

—

まとめ

`::view-transition-new` は、単なる「アニメーション用のフック」ではない。ウェブサイトの静的な限界を突破し、アプリのようなシームレスな体験をCSSだけで構築するための強力な武器だ。

仕様は常に進化しているし、ブラウザのサポート状況もChromium系を皮切りに広がっている(SafariもWebKitの実験的フラグから着実に実装が進んでいる)。今のうちにこの概念をマスターしておけば、将来必ずチームの主軸として重宝されるはずだ。

さて、理論はここまでだ。まずは手元の開発環境で、さっきのサンプルコードをコピーして試してみな。動かしてみて疑問が出たら、いつでも俺のところに聞きに来い。応援してるぞ!

コメント

タイトルとURLをコピーしました