お題と背景
モーダルはアクティブなサーフェスとして振る舞い、背景は表示されたまま操作不能である必要があります。実装では起動要素(opener)を保持し、Escape キーや閉じるコントロールをサポートし、正の tabindex による複雑な迷路に頼らないようにする必要があります。
面接官がテストするポイント
inert属性が何をブロックし、何を設定しないかの理解。- ネイティブな dialog セマンティクス、フォーカス管理、アクセシブルな名前付けの組み合わせ。
- ネストされたポータル、アニメーションのタイミング、ブラウザサポート、および視覚効果の抑制(reduced motion)の処理。
回答前の確認質問
- これはモーダルダイアログですか、それとも背景の操作を許可する非モーダルなポップオーバーですか?
- どの要素がダイアログを所有し、ポータルはどこにマウントされていますか?
- 開いたとき、キャンセル時、送信時、閉じたときにフォーカスはどうなるべきですか?
- ブラウザのベースラインは利用可能ですか、それとも古いクライアント向けのフォールバックが必要ですか?
30秒の回答フレームワーク
可能であればネイティブのモーダル dialog を使用し、ラベル付けされた見出しまたは最初の意味のあるコントロールにフォーカスを移動させ、ダイアログが開いている間は外部のアプリケーションシェルのみを inert としてマークします。起動要素が存在する場合はそこにフォーカスを復帰させ、Escape キーと明示的な閉じるボタンを提供し、キーボードとスクリーンリーダーのパスをテストします。inert は背景との操作を防ぎますが、ダイアログの名前付け、フォーカス復帰、または状態管理の代わりにはなりません。
ステップごとの詳細解説
1. 適切なセマンティックサーフェスを選択する
ブラウザのベースラインが許す場合は、真のモーダルに対して showModal() を持つネイティブの dialog 要素を使用し、表示されている見出しまたは aria-labelledby を介してアクセシブルな名前を提供します。非モーダルな開閉(disclosure)では、ユーザーがサーフェス間を移動することが想定されるため、ページ全体を inert にすべきではありません。
2. 背景を分離する
ダイアログポータルも含む共通の祖先ではなく、ダイアログの外側にあるアプリケーションコンテナに inert を適用します。ブラウザは inert なサブツリーをフォーカスナビゲーションから除外し、フォーカスイベントを防止します。また、通常のユーザーインタラクションも防ぎます。フォーカスされたダイアログを含む祖先に aria-hidden を不用意に設定しないでください。
3. フォーカスのライフサイクルを管理する
開く前に起動要素をキャプチャします。開いたときは、任意の閉じるアイコンではなく、安定した見出しや最初のタスクコントロールにフォーカスを当てます。キャンセルまたは送信が成功した場合は、ダイアログを閉じ、inert を削除し、起動要素が表示されていて有効なままであればフォーカスを復帰させます。起動要素が削除された場合は、論理的に近いターゲットを選択し、結果をアナウンスします。
4. ポータルとトランジションを処理する
クリッピングやスタッキングコンテキストに閉じ込められないよう、最上位レイヤーにダイアログをレンダリングします。モーダルの状態を操作に公開する前に inert を設定し、ダイアログがマウントされるまでフォーカスを遅延させます。開始・終了アニメーションを reduced-motion の設定と協調させます。中断されたトランジションの後に背景を inert のまま放置しないでください。
5. 失敗パスをテストする
Tab と Shift+Tab、Escape、閉じるボタンのアクティベーション、バリデーションエラー、ネストされたダイアログ、ルート変更、スクリーンリーダーのアナウンスをテストします。クリック、プログラムによるフォーカス、ページ内検索の動作、ポインターイベントがブラウザの inert の動作と一致していることを検証します。サポート対象のブラウザセットで必要な場合にのみフォールバックを追加し、ネイティブの動作が信頼できるようになったら削除します。
高品質な回答例
「真のモーダルでは、ネイティブのダイアログを使用し、ラベル付けされた見出しまたは最初のタスクコントロールにフォーカスを当て、ダイアログを含むポータルの祖先ではなく、外部のアプリケーションシェルに inert を設定します。起動要素をキャプチャし、閉じた後にフォーカスを復帰させ、Escape と明示的な閉じるボタンをサポートし、名前付けやバリデーションのセマンティクスを不活性化(inertness)とは分離して維持します。中断されたトランジションの後に inert 状態をクリアすることを含め、キーボード、スクリーンリーダー、ポータル、アニメーション、ルート変更のパスをテストします。」
よくある間違い
- ポータルを含むアプリのルートに inert を設定する → ダイアログも inert になる → inert なサブツリーの外側にダイアログをマウントする。
- inert をフォーカス管理システムとして使用する → 開閉時にフォーカスが依然として誤った場所に移動する可能性がある → 完全なフォーカスライフサイクルを定義する。
- フォーカスが含まれている状態で aria-hidden で背景を隠す → 支援技術が一貫性のない状態を認識する → 先にフォーカスを移動し、背景に inert を使用する。
- 中断されたトランジションを忘れる → ページがロックされたままになる → すべての閉じるパスとアンマウントパスで inert 状態をクリアする。
フォローアップ質問と回答
inert はフォーカストラップの代わりになりますか?
背景がフォーカス可能になるのを防ぐため、モーダルで手書きのトラップを不要にできることがよくあります。ただし、初期フォーカスの配置、復帰、ダイアログの名前付け、ブラウザやコンポーネントのフォールバックの処理は依然として必要です。
非モーダルなドロワーで inert を使用できますか?
プロダクトが意図的に背景を利用不可にする場合に限られます。背景の操作を許可する非モーダルなドロワーでは、ページを inert としてマークせず、代わりに適切な開閉(disclosure)セマンティクスを使用してください。
起動要素が消えた場合はどうなりますか?
更新された行やページの見出しなど、最も論理的に近いコントロールにフォーカスを復帰させ、必要に応じて結果をアナウンスします。切り離された要素や無効化された要素にフォーカスを合わせようとしないでください。