モーダル遷移完全ガイド|開閉アニメーション・画面階層・アクセシビリティの設計方法
モーダルは、現在の画面を完全に離れることなく、確認、入力、選択、警告などの重要な作業を利用者へ求めるUIです。商品をカートへ追加した後の確認、会員登録、画像の拡大表示、削除確認、支払方法の選択など、Webサイトやアプリケーションのさまざまな場面で使用されています。
モーダルの内容が分かりやすくても、表示や終了の遷移が不自然であれば、利用者は何が起きたのか理解できません。突然画面中央へ現れる、背景が遅れて暗くなる、閉じた後に元の場所へ戻れないといった問題は、操作の流れを中断し、誤操作や離脱につながります。
本記事では、モーダル遷移の目的、表示アニメーション、終了アニメーション、背景処理、画面階層、フォーカス管理、スマートフォン対応、ECサイトでの活用方法を詳しく解説します。CSS、JavaScript、Reactによる実装例も含め、見た目の演出ではなく、操作の理解と完了を支えるモーダル設計を紹介します。
1. モーダル遷移とは
モーダル遷移とは、通常画面からモーダルを表示し、操作完了または中止後に元の画面へ戻るまでの視覚的・操作的な変化です。モーダル本体の拡大や移動だけでなく、背景の暗転、スクロール停止、フォーカス移動、閉じた後の復帰まで含みます。
モーダルを一つの浮動要素としてだけ考えると、画面全体との関係が弱くなります。どの操作から開かれ、何を求め、終了後にどの状態へ戻るかを一連の遷移として設計する必要があります。
1.1 モーダルが表示される仕組み
モーダルを開くと、通常は既存画面の上へ新しい層が追加されます。背景は暗くなり、前面にダイアログ領域が表示され、利用者の操作対象が一時的に限定されます。
この変化によって、利用者は通常画面から一時的な作業へ移ったことを理解します。モーダル本体だけを表示し、背景や操作範囲を変えなければ、通常画面との階層差が伝わりにくくなります。
1.2 通常の画面遷移との違い
通常の画面遷移では、現在のページから別ページへ移動し、情報構造上の現在位置も変わります。モーダルでは、元の画面を維持したまま、その上で限定的な作業を行います。
そのため、モーダルを閉じた後は、元の画面状態へ自然に戻る必要があります。スクロール位置、選択状態、入力内容などが失われると、通常のページ移動より大きな負担を感じる場合があります。
| 比較項目 | モーダル遷移 | 通常の画面遷移 |
|---|---|---|
| 背景画面 | 維持される | 別画面へ置き換わる |
| 主な用途 | 確認、短い入力、補助作業 | 詳細閲覧、長い作業 |
| 終了後 | 元の状態へ戻る | 戻る操作で前画面へ移動 |
| 操作範囲 | 一時的に限定 | 新しい画面全体 |
| URL | 変わらない場合が多い | 変わる場合が多い |
1.3 モーダル表示の開始点
モーダルは、ボタン、リンク、画像、商品カードなどの操作から開かれます。開始点が明確であれば、利用者はどの操作によってモーダルが表示されたか理解しやすくなります。
画像拡大モーダルであれば、選択した画像付近から拡大する表現が関係性を伝えます。削除確認モーダルであれば、削除ボタンの近くで最初の反応を示し、その後に中央の確認画面を表示する方法があります。
1.4 モーダル終了後の復帰点
モーダルを閉じた後は、開く前に操作した要素へフォーカスを戻します。キーボード利用者は、どこから作業を再開すればよいか理解できます。
視覚的にも、モーダル終了後に背景画面が大きく移動しないことが重要です。スクロール位置や商品一覧の位置が変わると、利用者は元の場所を探し直さなければなりません。
1.5 遷移全体で設計すべき要素
モーダル遷移では、開始操作、背景の変化、本体の入場、フォーカス移動、内部操作、終了、本体の退場、背景復帰、フォーカス復帰を設計します。
アニメーションだけを作り込み、フォーカスや背景スクロールを放置してはいけません。モーダルは視覚表現と操作制御が一体になったUIです。
2. モーダル遷移を使用する目的
モーダルは、利用者の注意を一時的に一つの作業へ集中させるために使用します。現在の文脈を維持しながら、短い確認や入力を完了できる点が主な利点です。
ただし、重要ではない情報までモーダルで表示すると、利用者の作業を頻繁に中断します。モーダルでなければ達成できない目的かを確認する必要があります。
2.1 重要な確認を求める
データ削除、注文確定、公開設定変更など、実行後の影響が大きい操作では、確認モーダルが役立ちます。利用者へ結果を説明し、実行と中止を選択させます。
すべての操作へ確認モーダルを付けると、利用者が内容を読まずに確定するようになります。簡単に元へ戻せる操作では、実行後に取り消し機能を提供する方が適している場合があります。
2.2 短い入力作業を完了させる
住所追加、クーポン入力、数量変更など、短い入力作業はモーダル内で完了できます。元の購入画面を離れないため、入力後に作業を続けやすくなります。
入力項目が多い場合や、複数段階の判断が必要な場合は、専用ページの方が適しています。モーダル内で長いスクロールを求める設計は避けます。
2.3 補足情報を表示する
サイズ表、配送条件、用語説明など、現在の作業を補助する情報をモーダルへ表示できます。利用者は元画面の状態を失わずに確認できます。
補足情報が購入判断の中心になる場合は、常に見える位置へ置くことも検討します。重要情報をすべてモーダル内へ隠すと、利用者が存在に気付かない可能性があります。
2.4 画像や動画を拡大する
商品画像、図表、動画などを大きく確認させる用途にもモーダルが使われます。背景を暗くすることで、前面の視覚情報へ集中しやすくなります。
拡大表示では、次の画像、前の画像、閉じる操作を分かりやすくします。画像だけを大きく表示し、閉じ方が分からない状態を作らないようにします。
2.5 作業の中断を最小限にする
別ページへ移動すると、読み込みや位置復帰が必要になります。モーダルなら、背景状態を保ったまま補助作業を完了できます。
ただし、モーダルを重ねて表示すると、元の文脈から離れすぎます。モーダル内から別モーダルを開く設計は原則として避け、必要であれば画面構造を見直します。
3. モーダルを構成する要素
モーダル遷移を設計するには、モーダル本体だけでなく、背景、見出し、操作、状態表示などを分けて考える必要があります。各要素には異なる役割があり、入場と退場の強さも異なります。
すべての要素を同時に大きく動かすのではなく、背景で階層を作り、本体で作業領域を示し、内部要素で内容を伝える順番にします。
3.1 背景を覆うオーバーレイ
オーバーレイは、元画面を暗くしたりぼかしたりする層です。背景画面が存在していることを残しながら、現在は操作対象ではないことを伝えます。
暗くしすぎると背景との関係が失われ、薄すぎるとモーダル本体が背景へ埋もれます。モーダル内容と背景の複雑さに合わせて調整します。
3.2 モーダル本体
モーダル本体は、見出し、説明、入力項目、ボタンなどを含む主要領域です。背景との境界が分かるよう、面、枠線、影などを使用します。
表示時には、透明度変化、小さな拡大、短い移動などを使用できます。複数の効果を強く重ねると、内容より演出が目立つため注意します。
3.3 見出しと説明文
見出しは、利用者が何を求められているかを最初に理解する要素です。「確認」「お知らせ」のような抽象的な見出しではなく、「この商品を削除しますか」のように具体的にします。
説明文では、操作の結果や必要な条件を伝えます。長い文章を表示する場合は、モーダルが適切な形式か再検討します。
3.4 主要操作と中止操作
モーダル内では、主要操作と中止操作の優先順位を明確にします。削除確認では「削除する」が危険な主要操作、「キャンセル」が中止操作になります。
二つのボタンを同じ色と大きさにすると、判断しにくくなります。ボタンの視覚階層と遷移中の動きの強さを一致させます。
3.5 閉じる操作
閉じる操作には、閉じるボタン、キャンセルボタン、Escapeキー、背景選択などがあります。用途によって許可する方法を決めます。
重要な入力を含むモーダルを背景選択だけで閉じると、入力内容が失われる可能性があります。未保存内容がある場合は、確認または保存状態の維持を検討します。
| 構成要素 | 主な役割 | 遷移の強さ |
|---|---|---|
| オーバーレイ | 背景を非活動状態にする | 控えめ |
| モーダル本体 | 作業領域を示す | 最も強い |
| 見出し | 作業目的を伝える | 本体と同時 |
| 内部コンテンツ | 詳細情報と入力 | 本体と近いタイミング |
| ボタン | 実行・中止 | 操作時に短く反応 |
| 閉じるボタン | モーダルを終了する | 控えめ |
4. モーダルの画面階層を設計する方法
モーダルは、背景画面より一段上の階層として認識される必要があります。単に中央へ白い箱を置くだけでは、固定カードや通知との違いが伝わらない場合があります。
背景、重なり順、影、位置、動きを組み合わせ、一時的な最上位の操作領域であることを示します。
4.1 背景画面を残す
モーダル表示中も背景画面を完全に消さず、暗くした状態で残します。利用者はモーダルを閉じれば元の作業へ戻れることを理解できます。
背景を大きくぼかすと、文脈を認識しにくくなります。ぼかしを使う場合も、ページ構造が分かる程度に抑えます。
4.2 重なり順を明確にする
固定ヘッダー、チャット、広告、通知などがモーダルより前面に表示されると、階層が崩れます。モーダル表示中にどの要素を残すかを決めます。
緊急通知など特別な要素を除き、通常の固定UIはオーバーレイの背後へ置きます。重なり順の数値を無秩序に増やさず、階層トークンとして管理します。
4.3 中央配置と端配置を使い分ける
確認ダイアログは中央配置が適しています。スマートフォンの選択メニューや簡単な操作では、画面下部から表示する形式が使いやすい場合があります。
配置によって動きの方向も変わります。中央モーダルは小さな拡大、下部モーダルは下から上への短い移動を使用すると構造を理解しやすくなります。
4.4 モーダル内部の階層を作る
モーダル内部でも、見出し、説明、入力、主要操作、補助操作の順に優先順位を付けます。外側の遷移が優れていても、内部が複雑なら作業は完了できません。
主要操作を画面下部へ固定する場合は、内容がボタンの背後へ隠れないようにします。スクロール可能なモーダルでは、固定領域と本文領域を明確に分けます。
4.5 他の浮動要素を停止する
モーダル表示中に背景のカルーセル、動画、アニメーションが動き続けると、注意が分散します。背景の自動的な動きを一時停止する方法があります。
モーダルを閉じた後は、必要に応じて元の状態を再開します。ただし、利用者が手動停止していた動きを勝手に再開しないようにします。
| 階層 | 対象要素 | 表示状態 |
|---|---|---|
| 第一層 | 通常ページ | 背景として維持 |
| 第二層 | オーバーレイ | 通常ページを覆う |
| 第三層 | モーダル本体 | 最前面の作業領域 |
| 第四層 | モーダル内通知 | 必要時のみ本体内で表示 |
| 最上位例外 | 緊急なシステム通知 | 使用を限定 |
5. モーダル表示時の入場遷移
モーダルの入場遷移は、通常画面から一時的な作業へ移ったことを示します。利用者が内容を読み始めるまでの待ち時間を増やさず、階層変化が分かる程度の動きにします。
一般的には、オーバーレイの透明度変化と、モーダル本体の小さな拡大または移動を組み合わせます。
5.1 オーバーレイを先に認識させる
オーバーレイは、背景操作が一時停止したことを伝えます。本体と同時、またはわずかに先に表示すると、画面階層の変化が自然になります。
オーバーレイだけが長時間先に表示されると、画面が反応しなくなったように見えます。時間差を付ける場合も、ごく短くします。
5.2 小さな拡大を使用する
中央モーダルでは、98%程度から100%へ拡大する動きが使えます。前面へ現れる印象を与えながら、視覚的な負担を抑えられます。
80%から100%のような大きな拡大は、内容が急接近する印象になります。重要な警告であっても、過剰な拡大は避けます。
5.3 短い移動を組み合わせる
モーダルを数ピクセル下から上へ移動すると、入場方向を示せます。移動距離は画面全体のスライドより小さくします。
中央モーダルが画面端から長距離移動すると、サイドパネルや下部シートとの意味の違いが曖昧になります。配置形式と移動方向を一致させます。
5.4 内容を遅らせすぎない
モーダル本体を表示した後、見出し、本文、ボタンを一つずつ長い時間差で出すと、操作可能になるまで待たされます。
要素ごとの時間差を使う場合も、全体が短時間で完了する範囲にします。確認モーダルでは、本体と内容をほぼ同時に表示する方が効率的です。
5.5 フォーカス移動と同期する
モーダルが完全に見える前にフォーカスだけが移動すると、キーボード利用者や音声読み上げ利用者に不自然な状態が伝わります。
本体を表示可能な状態にした後、見出し、最初の入力項目、閉じるボタンなど適切な要素へフォーカスを移します。視覚表示と操作状態を同期させます。
コード例:中央モーダルの入場遷移
.modal-overlay { opacity: 0; transition: opacity 180ms cubic-bezier(0.2, 0, 0, 1);}
.modal-dialog { opacity: 0; transform: translateY(8px) scale(0.98);
transition: opacity 220ms cubic-bezier(0.2, 0, 0, 1), transform 220ms cubic-bezier(0.2, 0, 0, 1);}
.modal[data-state="open"] .modal-overlay { opacity: 1;}
.modal[data-state="open"] .modal-dialog { opacity: 1; transform: translateY(0) scale(1);}
6. モーダル終了時の退場遷移
退場遷移は、モーダル作業が終了し、背景画面へ戻ることを示します。入場より短くし、利用者が次の作業へ早く戻れるようにする方法が一般的です。
ただし、退場アニメーションを開始した瞬間にモーダル要素を削除すると、動きが表示されません。視覚的な終了とDOM上の削除を分けて制御します。
6.1 本体を先に退場させる
モーダル本体を先に縮小または透明化し、その後にオーバーレイを消すと、前面の作業領域が閉じたことを理解しやすくなります。
時間差は短くし、背景が暗いまま長く残らないようにします。本体とオーバーレイを同時に終了する方法でも問題ありません。
6.2 入場より短い時間を使う
利用者はすでにモーダル内容を確認しているため、終了時に長い演出は必要ありません。入場が220ミリ秒なら、退場を140ミリ秒から180ミリ秒程度にする方法があります。
ただし、大きな下部シートなど、移動距離が長い要素を極端に短くすると不自然になります。距離に応じて調整します。
6.3 確定後の結果を先に伝える
購入、保存、削除などを実行した場合は、モーダルを閉じる前または閉じた直後に結果を伝えます。何も表示せず閉じると、処理が成功したか分かりません。
背景画面の対象要素を更新し、必要に応じて短い通知を表示します。モーダル終了と結果更新を一つの流れとして設計します。
6.4 フォーカスを元へ戻す
退場アニメーションの完了後、モーダルを開いた要素へフォーカスを戻します。開いた要素が削除された場合は、次に適切な要素を選びます。
例えば商品削除モーダルで商品自体が消えた場合は、次の商品、一覧見出し、削除完了通知などへフォーカスを移します。
6.5 閉じる途中の再操作を防ぐ
退場中に再度閉じるボタンや確定ボタンが押されると、重複処理が発生する可能性があります。終了開始後は、必要な操作を一時的に無効化します。
ただし、アニメーション時間が長いほど操作不能時間も増えます。退場時間を短くし、処理状態を明確にします。
コード例:退場後に要素を非表示にする
const modal = document.querySelector("[data-modal]");const dialog = modal.querySelector(".modal-dialog");
function closeModal() { if (modal.dataset.state === "closing") { return; }
modal.dataset.state = "closing";
dialog.addEventListener( "transitionend", () => { modal.hidden = true; modal.dataset.state = "closed"; }, { once: true }, );}
7. オーバーレイの遷移を設計する方法
オーバーレイは、モーダル本体より目立つ必要はありませんが、画面階層を伝える重要な要素です。背景操作が停止していることを示し、前面の内容へ視線を集中させます。
色、透明度、ぼかし、クリック動作を適切に組み合わせます。装飾目的で複雑な背景変形を加える必要はありません。
7.1 透明度を段階的に変える
オーバーレイは、透明から半透明へ短時間で変化させます。突然暗くするより画面状態の変化を追いやすくなります。
透明度が低すぎると、背景の文字や画像がモーダル内容と競合します。背景の情報量が多いページでは、少し強めの暗転が必要です。
7.2 色を用途に合わせる
一般的には黒系の半透明色が使われますが、ブランドや画面テーマに合わせて濃い青やグレーを使用することもできます。
赤や鮮やかな色のオーバーレイは、警告の意味を強くしすぎる場合があります。危険操作であっても、モーダル本体の見出しやボタンで意味を伝える方が安定します。
7.3 背景ぼかしを慎重に使う
背景をぼかすと、モーダル本体を分離しやすくなります。しかし、処理負荷が増えたり、低性能端末で滑らかに動かなかったりする場合があります。
背景文脈を残すことも重要です。強いぼかしによって元画面が完全に判別できない場合は、単純な暗転へ置き換えます。
7.4 背景選択で閉じる条件を決める
画像拡大や軽い補足情報では、オーバーレイを選択して閉じられると便利です。重要な確認や入力モーダルでは、意図しない終了を防ぐため無効にする場合があります。
背景選択で閉じる場合でも、閉じるボタンを用意します。利用者が操作方法を推測しなくてもよい状態にします。
7.5 オーバーレイ上の操作を防ぐ
オーバーレイの背後にあるボタンやリンクが操作できると、利用者は意図しない処理を実行する可能性があります。ポインター操作だけでなく、キーボードフォーカスもモーダル内へ限定します。
単にpointer-eventsを設定するだけでは、Tabキーによる移動を防げません。フォーカス制御と背景の非活動化を合わせて実装します。
8. モーダルのサイズと位置に合わせて遷移を変える方法
すべてのモーダルに同じ遷移を使う必要はありません。小さな確認ダイアログ、長い入力フォーム、画面全体のモーダルでは、適切な移動距離や表示方向が異なります。
サイズと配置が持つ意味を保ちながら、モーダルの種類ごとに遷移を定義します。
8.1 小型確認モーダル
小型モーダルは、削除確認や短い選択に適しています。画面中央で、小さな拡大と透明度変化を使うと自然です。
内容が短いため、入場時間も短くできます。大きな移動や段階表示は必要ありません。
8.2 中型入力モーダル
住所追加や設定変更など、複数の入力項目を含むモーダルでは、中央または少し上に配置します。キーボード表示後も操作できる高さを確保します。
表示時に大きく拡大すると、入力欄が移動して見えます。小さな移動と透明度変化を中心にします。
8.3 大型モーダル
複雑な設定、画像一覧、比較画面などでは、画面の大部分を使うモーダルが必要になる場合があります。大型モーダルは、通常ページとの差が小さくなりやすいため、見出しと閉じる操作を明確にします。
画面全体を長距離で拡大するより、透明度と短い位置変化を使用します。作業が長い場合は、専用ページへの変更も検討します。
8.4 全画面モーダル
スマートフォンでは、長いフォームや複雑な選択を全画面モーダルとして表示できます。通常のページに近い構造ですが、完了または閉じると元画面へ戻ります。
全画面モーダルでは、横方向または下から上への遷移を使えます。通常ページ遷移との違いを、閉じる操作や戻り先で明確にします。
8.5 下部シート
選択肢、並び替え、簡単な確認などでは、画面下部から表示するシートが適しています。親指で操作しやすい位置へ主要操作を置けます。
下部から上へ移動し、閉じる際は下へ戻します。画面上部から表示すると、下部シートとしての構造が伝わりにくくなります。
| モーダル形式 | 主な用途 | 適した遷移 |
|---|---|---|
| 小型中央 | 確認、警告 | 小さな拡大、透明度 |
| 中型中央 | 短いフォーム | 短い上方向移動 |
| 大型中央 | 詳細設定、一覧 | 透明度、わずかな移動 |
| 全画面 | 長い作業 | 横移動、下から上 |
| 下部シート | 選択、並び替え | 下から上 |
9. スマートフォンのモーダル遷移
スマートフォンでは、画面の狭さ、片手操作、ソフトウェアキーボード、画面回転などを考慮する必要があります。デスクトップ用の中央モーダルを縮小するだけでは、操作しにくくなります。
モーダルの内容量に応じて、下部シート、全画面表示、中央ダイアログを使い分けます。
9.1 片手操作を考慮する
主要操作を画面下部へ配置すると、片手で押しやすくなります。キャンセルと確定の間隔を確保し、誤操作を防ぎます。
ただし、危険操作を親指が自然に触れる位置へ強く配置すると、誤確定の可能性があります。操作の重要性に応じて配置を調整します。
9.2 キーボード表示に対応する
入力欄へフォーカスすると、ソフトウェアキーボードによって表示領域が小さくなります。モーダル全体が上へ押し出され、見出しや閉じるボタンが隠れないようにします。
入力中の項目と主要操作が見えるよう、内部スクロールを設計します。固定ボタンがキーボードの背後へ隠れないことも確認します。
9.3 画面端の安全領域を確保する
端末によっては、画面下部や上部にシステム操作領域があります。全画面モーダルや下部シートでは、安全領域を考慮した余白が必要です。
単純な固定余白では、端末ごとに過不足が生じます。環境に応じた安全領域値を利用します。
9.4 スワイプ終了を提供する
下部シートでは、下方向のスワイプで閉じられると自然です。ただし、内部スクロールとの競合が起きやすいため、開始位置や移動量を慎重に設計します。
スワイプだけに依存せず、閉じるボタンやキャンセル操作も提供します。運動操作が難しい利用者でも終了できる必要があります。
9.5 画面回転へ対応する
縦向きから横向きへ変わった際、モーダルが画面外へ出たり、高さが不足したりしないようにします。
回転中に遷移アニメーションを再実行すると、内容が大きく動く場合があります。配置変更と入場遷移を分け、回転時は必要最小限の変化にします。
| スマートフォン特有の条件 | 主な問題 | 改善方法 |
|---|---|---|
| 片手操作 | 上部ボタンへ届きにくい | 主要操作を下部へ配置 |
| キーボード | 入力欄が隠れる | 内部スクロールを使用 |
| 安全領域 | ボタンがシステムUIと重なる | 環境余白を適用 |
| スワイプ | 内部スクロールと競合 | 操作範囲を限定 |
| 画面回転 | 高さと幅が変化する | 柔軟な最大サイズを使用 |
10. フォームモーダルの遷移を設計する方法
フォームモーダルでは、表示と終了だけでなく、入力、検証、エラー、送信中、完了などの状態遷移が発生します。各状態を一貫した順序で伝えることが重要です。
入力中にモーダルサイズが頻繁に変化すると、視線と操作位置がずれます。エラー領域や補助文の表示場所を事前に確保する方法があります。
10.1 最初の入力項目へ導く
モーダル表示後、見出しを読み終えた流れで最初の入力項目へ進める構造にします。自動的にフォーカスする場合は、モバイルでキーボードが即座に開く影響も考慮します。
説明を読む必要があるモーダルでは、最初の入力欄ではなく見出しへフォーカスを置く方法があります。
10.2 エラー表示で高さを急変させない
入力欄の下へエラーメッセージが追加され、モーダル全体が大きく移動すると、利用者が現在位置を見失います。
メッセージ用の領域を確保するか、短い透明度変化で表示します。エラー位置へスクロールする場合も、過度に長い滑らかな移動を避けます。
10.3 送信中の状態を示す
確定ボタンを押した後は、処理中であることをボタン内やモーダル内に表示します。ボタンを無効化し、重複送信を防ぎます。
送信中にモーダルを閉じられるかも決めます。閉じても処理が続く場合は、その結果を背景画面で伝えます。
10.4 成功後の終了方法を決める
送信成功後に即座にモーダルを閉じる方法と、モーダル内で完了状態を表示する方法があります。利用者が結果を確認する必要性によって使い分けます。
簡単な保存なら背景通知で十分です。注文確定や重要な登録では、完了内容をモーダルまたは専用画面で確認させます。
10.5 未保存内容を保護する
入力途中で閉じる操作が行われた場合、内容を破棄してよいか判断します。短い任意入力なら閉じてもよい場合がありますが、長いフォームでは確認が必要です。
確認モーダルをさらに重ねるのではなく、同じモーダル内で未保存警告へ切り替える方法もあります。モーダルの多重化を避けます。
コード例:送信状態を属性で管理する
async function submitModalForm(form, submitButton) { if (form.dataset.state === "submitting") { return; } form.dataset.state = "submitting"; submitButton.disabled = true; submitButton.textContent = "送信中"; try { await saveFormData(new FormData(form)); form.dataset.state = "completed"; submitButton.textContent = "保存しました"; } catch (error) { form.dataset.state = "error"; submitButton.disabled = false; submitButton.textContent = "もう一度送信"; } }
11. ECサイトでモーダル遷移を活用する方法
ECサイトでは、カート追加、商品選択、クーポン入力、配送確認などでモーダルが使われます。購入を助ける目的で使用すべきであり、販促表示によって作業を中断しすぎてはいけません。
購入段階が進むほど、不要なモーダルを減らし、注文完了へ集中できるようにします。
11.1 カート追加モーダル
商品をカートへ追加した後、追加商品、数量、価格を確認するモーダルを表示できます。買い物を続けるか、カートへ進むかを選択させます。
ただし、商品を追加するたびに大きなモーダルが表示されると、まとめ買いの邪魔になります。小さな通知やミニカートと比較し、商品カテゴリに合った形式を選びます。
11.2 商品オプション選択
色、サイズ、数量などを選ばなければ購入できない商品では、商品カードからオプション選択モーダルを開けます。
選択肢が多い場合や、仕様説明が必要な場合は商品詳細ページへ移動させた方が安全です。モーダル内で複雑な選択を求めると誤購入が増える可能性があります。
11.3 クーポン入力
カート画面でクーポンコード入力モーダルを使用できます。適用後は、割引額と新しい合計金額を明確に表示します。
モーダルを閉じるだけでなく、背景の注文金額も更新します。割引が適用されたか分からない状態を残さないようにします。
11.4 配送・返品条件の確認
配送日、送料、返品条件などを補足モーダルで表示できます。購入画面を離れずに条件を確認できます。
購入判断へ大きく影響する条件は、モーダルを開かなくても概要が分かるようにします。重要条件を完全に隠さないことが重要です。
11.5 離脱防止モーダル
ページを離れようとした利用者へ割引や会員登録を表示するモーダルがあります。しかし、意図しない表示や繰り返し表示は、信頼を低下させます。
表示頻度、対象利用者、閉じる操作を慎重に設定します。決済中や入力中に販促モーダルを表示してはいけません。
| ECでの用途 | モーダル適性 | 注意点 |
|---|---|---|
| 商品画像拡大 | 高い | 閉じる・画像移動を明確にする |
| サイズ表 | 高い | 重要情報の概要は元画面にも表示 |
| カート追加確認 | 商品により異なる | 購入を中断しすぎない |
| クーポン入力 | 比較的高い | 適用結果を背景へ反映 |
| 長い商品設定 | 低い場合がある | 専用ページを検討 |
| 強制的な販促 | 低い | 頻度と表示条件を制限 |
12. モーダルのアクセシビリティ対応
モーダルは、視覚的に前面へ表示するだけでは不十分です。キーボード、音声読み上げ、拡大表示、動きを減らす設定でも、現在の作業領域が理解できる必要があります。
特にフォーカス制御、利用可能な名前、背景の非活動化、閉じる操作は重要です。
12.1 ダイアログとして意味を設定する
モーダル本体には、ダイアログであることを支援技術へ伝える意味を設定します。見出しと説明文を関連付け、何のモーダルか理解できるようにします。
見た目がモーダルでも、適切な意味がなければ、音声読み上げ利用者には通常のコンテンツとして扱われる可能性があります。
12.2 フォーカスをモーダル内へ移す
モーダル表示後は、見出し、最初の入力、閉じるボタンなどへフォーカスを移します。用途に応じて最適な開始位置を選びます。
危険な確認モーダルで、削除ボタンへ自動フォーカスを置くと誤実行の可能性があります。キャンセル、見出し、説明などを開始位置にすることを検討します。
12.3 フォーカスを内部に保つ
Tabキーで移動しても、フォーカスが背景画面へ出ないようにします。最後の操作要素から次へ進むと、最初の操作要素へ戻します。
背景要素を単に暗くするだけでは、キーボード操作を防げません。背景を操作対象から外す処理が必要です。
12.4 Escapeキーで終了できるようにする
軽いモーダルでは、Escapeキーで閉じられると便利です。重要な処理中や未保存内容がある場合は、確認または別の対応が必要です。
Escapeキーを無効にする場合でも、明確な閉じる操作を提供します。利用者をモーダル内へ閉じ込めないようにします。
12.5 動きを減らす設定へ対応する
動きを減らす設定が有効な場合は、拡大、長距離移動、背景視差などを削減します。短い透明度変化または即時表示へ置き換えます。
アニメーションをなくしても、オーバーレイ、見出し、フォーカス移動によってモーダル開始が理解できる必要があります。
コード例:アクセシブルなモーダル構造
<div class="modal" data-modal hidden> <div class="modal-overlay" data-modal-close ></div>
<section class="modal-dialog" role="dialog" aria-modal="true" aria-labelledby="modal-title" aria-describedby="modal-description" > <h2 id="modal-title"> 商品を削除しますか </h2>
<p id="modal-description"> この操作は元に戻せません。 </p>
<div class="modal-actions"> <button type="button" data-modal-close> キャンセル </button>
<button type="button" class="danger-action"> 削除する </button> </div> </section></div>
コード例:動きを減らす設定
@media (prefers-reduced-motion: reduce) { .modal-overlay, .modal-dialog { transition-duration: 1ms; }
.modal-dialog { transform: none; }}
13. CSSでモーダル遷移を実装する方法
CSSでは、透明度、位置、拡大率を状態属性に応じて変更できます。表示状態と終了状態を明確に分けると、JavaScript側の処理も単純になります。
display: noneから直接アニメーションさせるのは難しいため、表示可能な状態にしてから遷移を開始し、終了後に非表示へ戻します。
13.1 状態属性を使用する
data-state="opening"、open、closingなどの属性で状態を管理します。クラス名でも実装できますが、状態の意味が分かる名前を使用します。
見た目のスタイルと処理状態を一致させることで、二重表示や退場途中の再表示を防ぎやすくなります。
13.2 opacityとtransformを中心に使う
入場と退場では、opacityとtransformを中心に使用します。幅や高さを連続変更すると、周囲の配置計算が増える可能性があります。
モーダル本体の最終サイズは先に決め、遷移中だけ位置や拡大率を変えます。
13.3 オーバーレイと本体を分ける
オーバーレイとモーダル本体を別要素として実装すると、透明度やタイミングを個別に調整できます。
一つの要素へ背景色と内容をまとめると、背景選択による終了や重なり順の管理が難しくなる場合があります。
13.4 スクロール可能領域を分ける
モーダル全体ではなく、本文部分だけをスクロール可能にすると、見出しと主要操作を維持できます。
ただし、モーダル内スクロールと背景スクロールが同時に動かないようにします。スクロールの境界で背景へ操作が伝わる問題も確認します。
13.5 CSS変数で時間を統一する
モーダル入場、退場、オーバーレイの時間をCSS変数として定義します。画面ごとに異なる数値を使わないようにします。
モーダルの種類によって異なる時間が必要な場合は、小型、大型、全画面などの用途別変数を用意します。
コード例:モーダル用CSS変数
:root { --modal-overlay-duration: 180ms; --modal-enter-duration: 220ms; --modal-exit-duration: 160ms;
--modal-enter-easing: cubic-bezier(0.2, 0, 0, 1);
--modal-exit-easing: cubic-bezier(0.4, 0, 1, 1);}
コード例:基本的なモーダルCSS
.modal { position: fixed; inset: 0; z-index: 1000; display: grid; place-items: center; padding: 1rem;}
.modal[hidden] { display: none;}
.modal-overlay { position: absolute; inset: 0; background: rgb(0 0 0 / 55%);}
.modal-dialog { position: relative; z-index: 1; width: min(100%, 32rem); max-height: min(90vh, 44rem); overflow: auto; border-radius: 1rem; background: #ffffff; box-shadow: 0 1.5rem 4rem rgb(0 0 0 / 25%);}
14. JavaScriptとReactでモーダルを制御する方法
JavaScriptでは、表示状態、終了タイミング、フォーカス、スクロール停止を管理します。Reactなどの画面ライブラリを使う場合でも、同じ状態遷移を設計する必要があります。
単純な開閉変数だけでは、退場アニメーション中に要素が削除される問題が起こります。表示状態と描画状態を分けます。
14.1 開いた要素を記録する
モーダルを開く前に、現在フォーカスされている要素を保存します。終了後にその要素へフォーカスを戻します。
開いた要素が削除された可能性も確認します。存在しない場合は、代替の復帰先を選びます。
14.2 requestAnimationFrameで入場を開始する
非表示要素を表示状態へ変更した直後に開いた状態を設定すると、ブラウザが開始状態を描画せず、アニメーションが省略される場合があります。
一度初期状態を描画してから、次の描画タイミングで開いた状態へ変更します。
コード例:モーダルを開く
let previouslyFocusedElement = null; function openModal(modal) { previouslyFocusedElement = document.activeElement; modal.hidden = false; modal.dataset.state = "opening"; requestAnimationFrame(() => { modal.dataset.state = "open"; const focusTarget = modal.querySelector( "[data-initial-focus], button, input, select, textarea", ); focusTarget?.focus(); }); }
14.3 退場完了を待って削除する
閉じる際は、状態をclosingへ変更し、アニメーションまたはトランジション完了後に非表示にします。
複数プロパティのtransitionendが発生する場合があります。対象要素やプロパティを限定するか、一回だけ処理します。
コード例:モーダルを閉じる
function closeModal(modal) { if (modal.dataset.state === "closing") { return; }
modal.dataset.state = "closing";
const dialog = modal.querySelector(".modal-dialog");
dialog.addEventListener( "transitionend", () => { modal.hidden = true; modal.dataset.state = "closed";
if ( previouslyFocusedElement && document.contains(previouslyFocusedElement) ) { previouslyFocusedElement.focus(); } }, { once: true }, );}
14.4 Reactで描画状態を分ける
Reactでは、isOpenだけで条件描画すると、falseになった瞬間にモーダルが削除されます。isMountedや遷移状態を別に持ち、退場完了後に削除します。
状態が増えるため、closed、opening、open、closingのような有限状態として管理すると分かりやすくなります。
コード例:Reactの状態管理
import { useEffect, useState } from "react";
export function Modal({ open, onClose, children }) { const [state, setState] = useState( open ? "open" : "closed" );
useEffect(() => { if (open) { setState("opening");
const frame = requestAnimationFrame(() => { setState("open"); });
return () => cancelAnimationFrame(frame); }
if (state !== "closed") { setState("closing"); } }, [open]);
if (state === "closed") { return null; }
return ( <div className="modal" data-state={state}> <button className="modal-overlay" aria-label="モーダルを閉じる" onClick={onClose} />
<section className="modal-dialog" role="dialog" aria-modal="true" onTransitionEnd={() => { if (state === "closing") { setState("closed"); } }} > {children} </section> </div> );}
14.5 ポータルを使用する
モーダルを通常のコンテンツ階層内へ配置すると、親要素のoverflowや重なり順の影響を受ける場合があります。画面最上位の専用領域へ描画する方法があります。
ただし、描画位置が変わっても、論理的な親子関係やイベント処理が正しく維持されることを確認します。
15. モーダル遷移を検証・改善する方法
モーダル遷移は、デザインツール上の再生だけでなく、実際のブラウザ、スマートフォン、キーボード操作で検証します。通信処理やエラー表示が加わると、試作時と異なる動きになる場合があります。
表示速度、理解、誤操作、アクセシビリティ、性能を複数の観点から確認します。
15.1 開いた理由が理解できるか確認する
利用者へ操作してもらい、モーダルがなぜ表示されたかを質問します。突然表示されたと感じる場合は、開始操作と遷移の関係が弱い可能性があります。
自動表示モーダルでは、利用者の作業を中断する価値があるかも確認します。表示条件そのものを見直す必要がある場合があります。
15.2 閉じ方が分かるか確認する
閉じるボタン、キャンセル、Escapeキー、背景選択など、利用可能な終了方法をテストします。閉じるアイコンだけでは、意味が分からない利用者もいます。
重要なフォームでは、誤って閉じた場合の入力保持も確認します。終了方法の多さより、予測できることが重要です。
15.3 フォーカス順を確認する
キーボードだけでモーダルを開き、内部を移動し、閉じた後に元の位置へ戻れるか確認します。
背景へフォーカスが抜ける、閉じた後にページ先頭へ戻る、非表示要素へフォーカスが残るといった問題を検出します。
15.4 低性能端末で確認する
背景ぼかし、大きな影、複数要素の同時移動は、低性能端末で遅れる場合があります。実際の対象端末で繰り返し開閉します。
遅延がある場合は、効果を減らし、透明度と短い移動だけへ置き換えます。滑らかでない複雑な演出より、単純で安定した遷移が優れています。
15.5 行動指標を確認する
モーダル表示後の完了率、閉じる割合、入力放棄率、重複クリック、エラー率などを確認します。
閉じる割合が高い場合、遷移が悪いだけでなく、表示内容、タイミング、対象利用者が適切でない可能性があります。UIだけに原因を限定せず、表示戦略全体を評価します。
| 検証項目 | 確認方法 | 主な問題 |
|---|---|---|
| 表示理解 | 利用者テスト | なぜ開いたか分からない |
| 終了操作 | キーボード・タッチ操作 | 閉じ方が見つからない |
| フォーカス | Tab・Escape操作 | 背景へ移動する |
| 表示性能 | 実機検証 | 動きが停止する |
| 入力保持 | 中断テスト | 内容が消える |
| 完了率 | 行動分析 | モーダル表示後に離脱する |
モーダル監査の記録例
対象モーダル:カート追加後の確認モーダル
表示目的:追加商品と購入金額を確認し、カートまたは買い物継続を選択させる。
発見した問題:・表示アニメーションが長い・背景カルーセルが動き続ける・閉じた後に商品一覧先頭へ戻る・スマートフォンで主要ボタンが画面外になる
改善内容:・入場時間を360ミリ秒から220ミリ秒へ短縮・モーダル表示中は背景カルーセルを停止・スクロール位置とフォーカスを復元・スマートフォンでは下部シートへ変更
確認指標:モーダル完了率、即時終了率、カート移動率、重複追加率
おわりに
モーダル遷移は、モーダル本体を拡大したり透明化したりするだけの演出ではありません。開始操作、背景の非活動化、モーダル表示、フォーカス移動、内部操作、終了、結果通知、元画面への復帰までを一つの流れとして設計する必要があります。
入場時は、オーバーレイと本体を短時間で表示し、利用者がすぐ内容を理解できるようにします。退場時は入場より短くし、処理結果を伝えたうえで、元の操作位置へ自然に戻します。モーダルのサイズ、配置、用途に応じて、中央拡大、下部からの移動、全画面遷移などを使い分けることも重要です。
さらに、キーボードフォーカス、Escapeキー、背景の非活動化、動きを減らす設定、低性能端末への対応を含めて検証する必要があります。モーダルを目立たせることではなく、利用者が迷わず作業を完了し、元の文脈へ戻れることが、優れたモーダル遷移の条件です。
EN
JP
KR