アクセシブルなカスタムUIを作るには、見た目を整えてからARIA属性を足すのではなく、最初に操作方法と状態の伝え方を決めます。
できるだけネイティブHTMLを使い、独自実装が必要な部分だけをWAI-ARIAとJavaScriptで補うのが基本です。
この記事では、ドロップダウン、モーダル、タブ、アコーディオンを例に、設計からテストまでの判断手順を整理します。
カスタムコンポーネントで起こる問題
カスタムコンポーネントとは、HTMLの標準要素だけでは表せない見た目や動作を、CSSやJavaScriptで組み立てたUI部品です。
独自の選択リスト、モーダル、タブ、アコーディオンなどが該当します。
見た目がボタンでも、単なる<div>として実装すると、ブラウザーはそれを操作部品として認識できません。
その結果、キーボードでフォーカスできない、スクリーンリーダーに名前や状態が伝わらない、開いた要素からフォーカスが外れるといった問題が生じます。
必要なのは、見た目、マウス操作、キーボード操作、支援技術に伝わる情報を同じ状態に保つことです。
WCAGとWAI-ARIAの役割
WCAG 2.2は、Webコンテンツのアクセシビリティを「知覚可能」「操作可能」「理解可能」「堅牢」の4原則から評価するための指針です。
WAI-ARIAは、HTMLだけでは十分に表せないUIの役割、名前、状態、要素同士の関係を支援技術へ伝える仕様です。
ARIAが見た目やキーボード操作を自動で実装するわけではありません。
ARIAの基本と使い分けは、関連記事のWAI-ARIAの役割と使い方でも解説しています。
| 原則 | コンポーネントで確認すること |
|---|---|
| 知覚可能 | ラベル、状態、エラー、選択結果を視覚だけに頼らず伝えられるか |
| 操作可能 | キーボードで到達して操作でき、フォーカス位置を見失わないか |
| 理解可能 | 同じ操作に同じ結果が伴い、開閉や選択の状態が予測できるか |
| 堅牢 | 役割、名前、状態がコード上で結び付き、支援技術に伝わるか |
WCAGの適合レベルは、記事の書き方だけで宣言できるものではありません。
対象ページやサイトを定め、該当する達成基準を実際に試験して判断します。
WCAG 2.2の変更点と実務での読み方は、WCAG 2.2で追加された達成基準の解説を参照してください。
実装前に決める五つのこと
- 目的:選択、開閉、画面の切り替えなど、利用者が行う操作を一つに絞ります。
- 標準要素:
<button>、<select>、<details>などで要件を満たせないか確認します。 - 役割と状態:必要な場合だけARIAのロール、プロパティ、状態を割り当てます。
- キーボード操作:使用するキー、フォーカスの移動先、操作後に戻す場所を決めます。
- 試験条件:マウスを使わない操作、拡大表示、スクリーンリーダーなど、確認方法を実装前に決めます。
標準要素を優先する理由は、意味と基本的な操作がブラウザーに組み込まれているためです。
たとえば、クリック処理を付けた<div>をボタンとして使うと、フォーカス、EnterキーやSpaceキーへの対応、無効状態などを個別に再実装する必要があります。
「ドロップダウン」は目的から分類する
ドロップダウンという呼び名だけでは、適切なHTMLやARIAのパターンは決まりません。
値を一つ選ぶUI、入力候補を表示するUI、リンクの一覧を開くUIは、それぞれ役割と操作方法が異なります。
| 利用者の目的 | 最初に検討する実装 | 注意点 |
|---|---|---|
| 候補から値を選ぶ | <select> |
独自表示が必須でなければ標準要素を使う |
| 文字を入力しながら候補を選ぶ | コンボボックス | 入力欄、候補一覧、選択状態の関係を定義する |
| 複数の選択肢を一覧で選ぶ | リストボックス | role='listbox'とrole='option'を組み合わせ、選択とフォーカスを区別する |
| リンクや操作項目を開く | ボタンと開閉領域 | リストボックスを流用せず、内容に合うパターンを選ぶ |
開閉ボタンには、現在の状態を示すaria-expandedと、操作対象を示すaria-controlsを必要に応じて設定します。
リストボックスでは上下矢印による移動などを実装しますが、リンクやチェックボックスを並べた領域を安易にrole='listbox'へ置き換えることはできません。
モーダルではフォーカスの流れを閉じる
モーダルは、開いている間、背後の画面を操作できないダイアログです。
視覚的に前面へ表示するだけでは、キーボード利用者のフォーカスが背後へ移動する可能性があります。
- ダイアログに
role='dialog'とaria-modal='true'を設定し、見出しなどからアクセシブルな名前を与える - 開いた直後に、内容を理解して操作しやすいダイアログ内の要素へフォーカスを移す
- TabキーとShift+Tabキーの移動範囲をダイアログ内に保つ
- Escapeキーと、ラベルを理解できる閉じるボタンを用意する
- 閉じた後は、原則としてモーダルを開いた要素へフォーカスを戻す
- 背後の要素を操作不能にし、ダイアログまで
aria-hidden='true'の配下に入れない
背景へ一律にaria-hidden='true'を付けるだけでは、キーボード操作を止められません。
表示、支援技術への伝達、実際の操作可否を同時に管理します。
タブは選択状態と表示パネルを結び付ける
タブでは、タブの一覧、各タブ、対応するパネルを明示します。
- 一覧に
role='tablist'、各タブにrole='tab'、内容にrole='tabpanel'を設定する - 各タブの
aria-controlsと各パネルのaria-labelledbyを対応させる - 選択中のタブだけを
aria-selected='true'にする - Tabキーでは選択中のタブへ入り、左右矢印キーでタブ間を移動できるようにする
- 選択状態、フォーカス、表示中のパネルを同じタイミングで更新する
パネルの表示に時間がかかる場合、矢印キーでフォーカスしただけでは切り替えず、EnterキーまたはSpaceキーで確定する方式も検討します。
アコーディオンは見出しと開閉ボタンを保つ
アコーディオンは、見出しに対応する内容を開閉するコンポーネントです。
見出しの中に<button>を置くと、文書構造と操作部品の両方を保てます。
- ボタンの
aria-expandedを開閉状態に合わせて更新する aria-controlsで対応するパネルを示す- EnterキーとSpaceキーで開閉できるようにする
- 閉じたパネルの内容がフォーカス順に残らないようにする
- 色やアイコンだけに頼らず、開閉状態をコードでも伝える
キーボード操作とフォーカスを同時に設計する
キーボード対応は、すべての要素をTabキーで巡回させることではありません。
複合コンポーネントでは、Tabキーでコンポーネントへ出入りし、矢印キーで内部を移動するパターンがあります。
| 操作 | 確認する挙動 |
|---|---|
| Tab、Shift+Tab | ページ上の操作対象を自然な順序で移動できる |
| Enter、Space | ボタンの実行や開閉ができ、意図しないページスクロールが起きない |
| 矢印キー | タブやリストボックスなど、採用したパターンに沿って内部を移動できる |
| Escape | モーダルなどを閉じ、操作を始めた場所へ戻れる |
| フォーカス表示 | 現在位置を背景色の違いだけに頼らず判別できる |
具体的な確認方法は、キーボード操作とフォーカス表示の実務チェックでも確認できます。
ARIAを増やす前に確認すること
名前、役割、状態を分けて考える
支援技術が操作部品を理解するには、何の部品かを示す役割、何をするかを示す名前、現在どうなっているかを示す状態が必要です。
aria-labelは名前を与える方法の一つですが、目に見えるラベルがある場合は、そのラベルと読み上げ名が食い違わないようにします。
動的な更新をすべて読み上げさせない
aria-liveは、操作後に別の場所で変わった結果など、フォーカスを移さず知らせる必要がある更新に使います。
装飾的な変化や頻繁な更新まで通知すると、必要な情報を聞き取りにくくなります。
表示とARIAの状態を同じ処理で更新する
パネルを開いたのにaria-expanded='false'が残ると、見た目と読み上げが矛盾します。
クラス名、表示状態、ARIA属性を別々の処理で変更せず、一つの状態を基に更新するとずれを防ぎやすくなります。
実装後のテスト手順
自動検査だけでは、操作の自然さや読み上げの文脈までは確認できません。
次の順序で手動確認と自動検査を組み合わせます。
- キーボードだけで操作する:すべての機能へ到達でき、フォーカスが消えたり閉じ込められたりしないか確認します。
- フォーカス表示を見る:通常時、ホバー時、フォーカス時を区別できるか確認します。
- スクリーンリーダーで確認する:名前、役割、開閉状態、選択状態、エラーが意図どおり伝わるか確認します。
- 拡大して確認する:文字や画面を拡大しても、操作部品や内容が重ならず利用できるか確認します。
- 色とコントラストを確認する:文字、境界、フォーカス表示を識別でき、色だけで状態を伝えていないか確認します。
- 自動検査を行う:ラベル不足、属性の不整合、コントラストなど、機械的に見つけやすい問題を補足します。
複雑な部品を作る場合は、WAI-ARIA Authoring Practicesのデザインパターンで、役割とキーボード操作を照合します。
公開前のチェックリスト
- 同じ要件をネイティブHTMLで満たせないか確認した
- 操作部品に理解できる名前がある
- 開閉、選択、無効などの状態が見た目とコードで一致している
- マウスを使わず、すべての機能を操作できる
- フォーカスの現在位置と移動先を確認できる
- スクリーンリーダーで役割、名前、状態を確認した
- 自動検査の結果を手動で再確認した
カスタムUIは状態と操作から設計する
アクセシブルなカスタムUIは、ARIA属性の数ではなく、利用者の操作とコンポーネントの状態が一貫して伝わるかで評価します。
標準要素を出発点にし、独自実装が必要な箇所だけを補い、キーボードと支援技術で確かめる流れを設計とレビューに組み込んでください。
