設問とコンテキスト
デザインシステムにおいて、ボタン、入力フィールド、メニュー、カスタムコントロール共通のキーボードフォーカス表現が必要です。現在の実装ではボーダーの色が変わるだけで、低コントラストテーマでは見えなくなり、フォーカス時にコンポーネントのサイズが変わってしまいます。再利用可能なアプローチとテストゲートを設計してください。
WCAG 2.2では、インジケーターの面積と隣接色とのコントラストに関する達成基準として「Focus Appearance(フォーカスの外観)」が追加されました。この面接では、単にアウトラインを追加するだけでなく、その要件をコンポーネントの状態、CSSデザイントークン、キーボード遷移パス、測定可能なチェックへと落とし込めるかを評価します。
面接官が見ているポイント
インジケーターとコンポーネントの明確な区別、面積とコントラストの計算、色のみに依存しない表現、非矩形および角丸コントロールへの対応、レイアウトシフトの防止、ネイティブセマンティクス、そして:focus-visible、ポインター入力、forced-colorsモードの網羅ができているかを確認します。
確認すべき質問
- 対象はWCAG 2.2 AAですか、それともAAAですか?またキーボード操作可能なパスはどれですか?
- フォーカスリングはコンポーネントの外側、内側、またはオフセットして配置しますか?
- どのようなテーマトークンとforced-colorsルールが存在しますか?
- カスタムコントロールはネイティブ要素を使用していますか、それとも適切なロールと状態を持っていますか?
- フォーカス、ホバー、選択中、無効(invalid)の状態はどのように合成されますか?
- 角丸コントロール、スクロール、画像背景はどのようにテストされますか?
30秒での回答
「操作可能な要素を洗い出し、可能な限りネイティブコントロールを使用し、色のみに依存しない:focus-visibleインジケーターを提供します。レイアウトを変更しないoutlineまたは疑似要素を使用し、リングのジオメトリと、コンポーネントおよび隣接する背景の両方に対するコントラストをトークン化します。forced-colorsモードではシステムカラーを維持します。完全なキーボードパス、レンダリングされたピクセル、ズーム、および手動の支援技術チェックで検証します。」
ステップ別の解決手順
ステップ 1: フォーカス対象と状態を定義する
ネイティブのボタン、input、select、リンクを優先します。カスタムdivにはキーボード処理、ロール、名前、値、状態の同期が必要です。focus-visibleはポインターとキーボードのフォーカスを区別するのに役立ちますが、キーボードのフィードバックを排除してはなりません。
デフォルト、ホバー、focus-visible、選択中、無効(invalid)、disabledの優先順位を定義し、エラーや選択スタイルが適用されている場合でもリングが識別できるようにします。
ステップ 2: レイアウトを変更せずに描画する
フォーカス時にボーダー幅を追加しないでください。ボックスサイズが変わり隣接要素を押し出してしまいます。outline、outline-offset、または疑似要素を優先してください。複雑な形状の場合は内側と外側のシャドウを組み合わせますが、クリッピングされないことを確認してください。
.control:focus-visible {
outline: 3px solid var(--focus-ring);
outline-offset: 2px;
}親要素によってクリップされる矩形の線ではなく、角丸ボタン、アイコンボタン、スライダーのレンダリングされた周囲長を評価してください。
ステップ 3: WCAG 2.4.13をトークンとしきい値に落とし込む
リング幅、オフセット、フォーカス色、背景、エラー状態のトークンを一元管理します。テキストだけでなく、非フォーカス時のコンポーネントおよび隣接する背景に対するコントラストをテストします。グラデーション、画像、または半透明レイヤーが存在する場合は、最も条件の悪い局所的な色をサンプリングします。
focus-ring-width >= 2 CSS px
focus-ring-contrast-against-adjacent >= required threshold
focus-ring-area >= minimum perimeter-area rule面積とコントラストの判定ゲートには、レンダリングされたジオメトリとピクセルを使用します。デザインファイル上の色はランタイムでの準拠の証明にはなりません。
ステップ 4: テーマ、強制カラー、システムオーバーライドをサポートする
ライト、ダーク、ブランドの各テーマに個別のフォーカストークンを割り当てます。forced-colors: active環境下では、プラットフォームのインジケーターを非表示にしないでください。ButtonTextなどのシステムカラーを使用することで視認性を維持できます。
@media (forced-colors: active) {
.control:focus-visible {
outline: 2px solid ButtonText;
outline-offset: 2px;
}
}同じ状態で同等に明確な可視インジケーターを提供しない限り、outline: noneを使用してはなりません。
ステップ 5: 動的コントロールとスクロールに対応する
メニュー、ダイアログ、コンボボックス、仮想リストでは、フォーカスの移動、閉じた際のフォーカスの復帰、スクロール中もリングが表示され続けることをテストする必要があります。transform、clip-path、overflowによってインジケーターが消えてはなりません。
aria-activedescendantを使用する場合、DOMフォーカスはコンテナに留まっていても視覚的なインジケーターはアクティブな項目に追従し、キーボードとスクリーンリーダーの表示が一致している必要があります。
ステップ 6: 自動および手動の受け入れ基準を構築する
フォーカス可能要素、計算されたoutlineやshadow、テーマトークン、forced-colorsルール、状態や背景にまたがるスクリーンショットのチェックを自動化します。手動でTab、Shift+Tab、Enter、Space、矢印キー、Escapeを使用し、さまざまな入力デバイスで200%ズームやハイコントラスト設定をテストします。
コンポーネント、状態、背景、リングのジオメトリ、コントラスト結果、キーボード操作ステップ、スクリーンショットを記録します。デザインファイルに見える青い線は準拠の証明にはなりません。
模範解答
「操作可能なコントロールを洗い出し、ネイティブセマンティクスを優先します。:focus-visibleではレイアウトに影響を与えないoutlineとoffsetを使用し、トークンによってリング幅とコントラストの一貫性を保ちます。フォーカスによってボーダー幅が追加されたり、色のみに依存したりしてはなりません。ライト、ダーク、forced-colorsモードをテストし、システムの視認性を維持します。」
「メニュー、ダイアログ、仮想リスト、非矩形コントロールについては、フォーカス移動、フォーカス復帰、クリッピング、アクティブ項目の表示を検証します。自動化によって計算されたスタイルとピクセルをキャプチャし、手動チェックでキーボードパス、200%ズーム、ハイコントラストを網羅します。」
よくある間違い
- テキストまたはボーダーの色のみを変更する → リングが背景に溶け込む → リングと隣接色を個別にテストする。
- ボーダー幅を追加する → レイアウトシフトが発生する → outlineまたはレイアウトに影響しない要素を使用する。
outline: noneを強制する → キーボードユーザーへのフィードバックが失われる → 同等の可視インジケーターを提供する。- ライトテーマのみテストする → ダークまたは強制カラーで見えなくなる → すべてのテーマモードを網羅する。
- 矩形のスクリーンショットのみを使用する → 角丸やクリップされたジオメトリが見落とされる → レンダリングされた形状とスクロールをテストする。
- divにフォーカスを当てる → セマンティクスと支援技術の出力が乖離する → ネイティブコントロールと有効なARIAを優先する。
フォローアップ質問と回答
フォローアップ 1: outlineはbox-shadowより優れていますか?
一概にどちらが優れているとは言えません。outlineはレイアウトに影響せずプラットフォームセマンティクスを持ちます。shadowは多層リングを作成できます。クリッピング、角丸のジオメトリ、forced-colorsの挙動、レンダリングピクセルの結果に応じて選択してください。
フォローアップ 2: なぜ:focus-visibleは:focusの代わりにならないのですか?
これはフォーカスを表示するかどうかのブラウザのヒューリスティクスです。フォーカスセマンティクスを削除したり、キーボードや支援技術のパスからフィードバックを奪ったりしてはなりません。
フォローアップ 3: エラー時の赤いボーダーはフォーカスリングの代わりになりますか?
いいえ。エラーは問題を伝え、リングは現在のターゲットを伝えます。色のみに依存することなく、両方が視認できる状態を維持する必要があります。
フォローアップ 4: 画像やグラデーションの背景はどのようにテストしますか?
レンダリングされたリングに隣接する最も条件の悪い局所的な色をサンプリングし、必要に応じて不透明な下地や2つ目のリングを追加します。デザインの平均色は証拠になりません。
フォローアップ 5: overflowによるリングのクリッピングをどのように防ぎますか?
親要素のoverflow、clip-path、transformを調査します。フォーカススタイルを無効にするのではなく、インナーリング、パディング、またはコンポーネントレベルの疑似要素を使用してジオメトリに合わせます。