HTML / CSS約9分

dialogでモーダルを開閉する:閉じる操作と戻る場所を確かめる

重なる箱が表示されるだけでは、モーダルの操作は完成しません。架空の資料室の案内を使い、dialogの開閉、閉じるボタン、Escape、呼び出し元へ戻るフォーカスを順に確かめます。

この記事の目次
  1. 背景を操作できない間に、何を終えるか決める
  2. 名前と閉じるボタンを持つ一枚を保存する
  3. open属性だけで背景を止めようとしない
  4. 閉じ方を一つに限定せず、復帰先も調べる
  5. 長い説明や重要な操作へ広げるときの境界
  6. 閉じた後、開くボタンから操作を続けられるか

画面の上に案内の箱は出たのに、Tabキーを押すと背景のリンクへ進んでしまう。dialogでモーダルを開閉する練習では、箱の表示だけでなく、操作できる範囲と閉じた後の行き先までを一組で確認します。

題材は架空の資料室の利用案内です。HTMLのidと、JavaScriptのイベント処理を少し読める人向けです。エディターとdialogに対応するブラウザーを用意します。送信、予約、削除は行わず、短い説明を開いて戻るだけの練習ページを作ります。

背景を操作できない間に、何を終えるか決める

モーダルとは、開いている間はその中の操作へ移り、背後のページを操作対象から外す表示です。今回は案内を読み、閉じて元のボタンへ戻るところまでを一つの操作にします。単に文章を隠したいだけなら、本文の途中で開けるdetailsの方が適切な場合もあります。

detailsによる補足の開閉では、読む流れを保ったまま補足を展開します。今回のdialogは、背景へTabで移れないことや、閉じた後に元の位置へ戻ることが検証対象です。表示を重ねる見た目だけで二つを選ばないようにします。

MDNのdialogにあるshowModal()は、モーダルとして開くためのメソッドです。open属性を付けるだけの表示と区別してください。背景を暗くするCSSだけを足しても、操作範囲の切り替えを作ったことにはなりません。

名前と閉じるボタンを持つ一枚を保存する

次をdialog-practice.htmlとして保存して開きます。scriptを本文の後ろへ置き、対象のボタンとdialogが存在してからイベントを登録します。動作はこの一枚で完結し、通信や保存はしません。

<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>資料室の案内を開く練習</title>
<style>
body { margin: 1rem; font-family: sans-serif; line-height: 1.8; }
button { font: inherit; padding: .5em 1em; }
button:focus-visible, a:focus-visible { outline: 3px solid #174ea6; outline-offset: 3px; }
dialog { box-sizing: border-box; width: min(30rem, calc(100% - 2rem)); max-height: calc(100% - 2rem); overflow: auto; padding: 1.5rem; }
dialog::backdrop { background: rgb(0 0 0 / .45); }
</style>
</head>
<body>
<h1>資料室(架空の練習)</h1>
<button type="button" id="open-guide">利用案内を開く</button>
<p><a href="#background-note">本文の補足へ</a></p>
<dialog id="guide" aria-labelledby="guide-title">
  <h2 id="guide-title">利用案内</h2>
  <p>閲覧した資料は受付の返却台へ置いてください。</p>
  <button type="button" id="close-guide" autofocus>案内を閉じる</button>
</dialog>
<p id="background-note">このページは開閉操作の練習用です。</p>
<script>
const opener = document.querySelector('#open-guide');
const dialog = document.querySelector('#guide');
const closer = document.querySelector('#close-guide');
opener.addEventListener('click', () => {
  if (!dialog.open) dialog.showModal();
});
closer.addEventListener('click', () => dialog.close());
dialog.addEventListener('close', () => opener.focus());
</script>
</body>
</html>

aria-labelledbyは、見えている見出しのidを参照してダイアログの名前を付けます。閉じるボタンにはautofocusを付け、開いた直後の操作場所を示します。短い説明だけなので、この例では閉じるボタンが最初の操作先です。

closeイベントで呼び出し元へフォーカスを戻すため、ボタンで閉じてもEscapeで閉じても同じ復帰処理になります。例では呼び出し元は一つで、閉じるまで文書内に残ります。複数の呼び出し元や、開いた後に元のボタンを削除する画面には、そのまま流用しません。

open属性だけで背景を止めようとしない

一つ目の失敗は、dialogへopen属性を足して表示し、モーダルが完成したと考えることです。箱は見えますが、背景の操作を止めるshowModalの呼び出しとは違います。Tabで背景へ移れてしまう場合は、CSSの重なり順より、開く方法を最初に確認してください。

修正は初期HTMLからopenを外し、完成例のようにボタンからshowModalを呼ぶことです。再確認では案内を開き、TabとShift+Tabを押しても背景の「本文の補足へ」を操作しないことを確かめます。見た目の暗さだけを合格条件にしないことが要点です。

また、JavaScriptが読み込まれなければ、この例の開くボタンは動きません。実サイトで利用に必須の案内を載せるなら、本文にも基本情報を残すか、通常のページへ進める導線を設計します。この練習コードだけを、そのまま必須情報の唯一の入口にはしません。

閉じ方を一つに限定せず、復帰先も調べる

二つ目の失敗は、Escapeで閉じられるからと、画面上の閉じるボタンを省くことです。物理キーボードのない場面では、終える場所が分かりません。修正では名前のある閉じるボタンを残し、タップとキーボードの両方で閉じられることを確かめます。

背景の暗い部分を押したときに閉じる動作は、この例には実装していません。「どこか押せば閉じるはず」と推測せず、明示した閉じる操作で終了できるかを確認してください。Escapeの標準の閉じる動作を取り消すイベント処理も追加しません。

W3C APGのモーダルの操作指針は、開いたときのフォーカスと、閉じた後に呼び出し元へ戻る流れを説明しています。復帰の処理を閉じるボタンのクリックだけへ置くと、別の閉じ方で扱いが分かれます。今回のcloseイベントは終了経路を一か所へまとめる役割です。

長い説明や重要な操作へ広げるときの境界

長い規約を表示する場合や、確認後に削除する場合は、最初のフォーカスを同じ閉じるボタンへ置けばよいとは限りません。読む順番や、安全に中止する方法を内容に合わせて設計します。この例は短い説明を読む練習なので、破壊的な操作の確認画面の完成例ではありません。

画面を作り直すアプリではイベントを重複登録しないことや、画面を破棄するときの後始末も必要です。今回は文書を読み込んだとき一度だけ登録し、文書を閉じれば要素ごと破棄される構成です。初期化関数を何度も呼ぶ構成へ変えるなら、登録と解除を対にします。

フォーカスの枠が見えない場合は、フォーカス表示を直す記事へ戻ります。buttonの代わりにクリックできるdivを置く修正はせず、リンクとボタンの役割も維持しましょう。

閉じた後、開くボタンから操作を続けられるか

ページを保存し、まずTabで「利用案内を開く」へ移り、Enterで開きます。次の結果を、一周ずつ記録してください。

  • 開いた直後に「案内を閉じる」へフォーカスが移る。
  • 開いている間、TabとShift+Tabで背景のリンクへ進まない。
  • 閉じるボタンを押すと箱が消え、元の開くボタンへ戻る。
  • もう一度開いてEscapeを押しても閉じ、同じボタンへ戻る。
  • 幅320pxでも説明と閉じるボタンを読め、必要なら箱の中をスクロールできる。

読み上げ環境があれば、利用案内という名前とダイアログの役割が伝わるかも確認します。未実施なら操作テストと分けて記録してください。アクセシビリティの無料レッスンに進む際も、表示の有無だけでなく、閉じた後に次の操作を続けられるかを確認条件に残しましょう。

記事についてのお問い合わせ

記載内容へのご質問や訂正のご連絡は、hello@junkbranding.comまでお願いします。

← 記事一覧に戻る