サイトアイコン IT & ライフハックブログ|学びと実践のためのアイデア集

アクセシブルなカスタムコンポーネントの作り方:WCAGとWAI-ARIAの実装・テスト手順

person in white long sleeve shirt using macbook pro

Photo by cottonbro studio on Pexels.com

アクセシブルなカスタム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で追加された達成基準の解説を参照してください。

実装前に決める五つのこと

  1. 目的:選択、開閉、画面の切り替えなど、利用者が行う操作を一つに絞ります。
  2. 標準要素<button><select><details>などで要件を満たせないか確認します。
  3. 役割と状態:必要な場合だけARIAのロール、プロパティ、状態を割り当てます。
  4. キーボード操作:使用するキー、フォーカスの移動先、操作後に戻す場所を決めます。
  5. 試験条件:マウスを使わない操作、拡大表示、スクリーンリーダーなど、確認方法を実装前に決めます。

標準要素を優先する理由は、意味と基本的な操作がブラウザーに組み込まれているためです。

たとえば、クリック処理を付けた<div>をボタンとして使うと、フォーカス、EnterキーやSpaceキーへの対応、無効状態などを個別に再実装する必要があります。

「ドロップダウン」は目的から分類する

ドロップダウンという呼び名だけでは、適切なHTMLやARIAのパターンは決まりません。

値を一つ選ぶUI、入力候補を表示するUI、リンクの一覧を開くUIは、それぞれ役割と操作方法が異なります。

利用者の目的 最初に検討する実装 注意点
候補から値を選ぶ <select> 独自表示が必須でなければ標準要素を使う
文字を入力しながら候補を選ぶ コンボボックス 入力欄、候補一覧、選択状態の関係を定義する
複数の選択肢を一覧で選ぶ リストボックス role='listbox'role='option'を組み合わせ、選択とフォーカスを区別する
リンクや操作項目を開く ボタンと開閉領域 リストボックスを流用せず、内容に合うパターンを選ぶ

開閉ボタンには、現在の状態を示すaria-expandedと、操作対象を示すaria-controlsを必要に応じて設定します。

リストボックスでは上下矢印による移動などを実装しますが、リンクやチェックボックスを並べた領域を安易にrole='listbox'へ置き換えることはできません。

モーダルではフォーカスの流れを閉じる

モーダルは、開いている間、背後の画面を操作できないダイアログです。

視覚的に前面へ表示するだけでは、キーボード利用者のフォーカスが背後へ移動する可能性があります。

背景へ一律にaria-hidden='true'を付けるだけでは、キーボード操作を止められません。

表示、支援技術への伝達、実際の操作可否を同時に管理します。

タブは選択状態と表示パネルを結び付ける

タブでは、タブの一覧、各タブ、対応するパネルを明示します。

パネルの表示に時間がかかる場合、矢印キーでフォーカスしただけでは切り替えず、EnterキーまたはSpaceキーで確定する方式も検討します。

アコーディオンは見出しと開閉ボタンを保つ

アコーディオンは、見出しに対応する内容を開閉するコンポーネントです。

見出しの中に<button>を置くと、文書構造と操作部品の両方を保てます。

キーボード操作とフォーカスを同時に設計する

キーボード対応は、すべての要素をTabキーで巡回させることではありません。

複合コンポーネントでは、Tabキーでコンポーネントへ出入りし、矢印キーで内部を移動するパターンがあります。

操作 確認する挙動
Tab、Shift+Tab ページ上の操作対象を自然な順序で移動できる
Enter、Space ボタンの実行や開閉ができ、意図しないページスクロールが起きない
矢印キー タブやリストボックスなど、採用したパターンに沿って内部を移動できる
Escape モーダルなどを閉じ、操作を始めた場所へ戻れる
フォーカス表示 現在位置を背景色の違いだけに頼らず判別できる

具体的な確認方法は、キーボード操作とフォーカス表示の実務チェックでも確認できます。

ARIAを増やす前に確認すること

名前、役割、状態を分けて考える

支援技術が操作部品を理解するには、何の部品かを示す役割、何をするかを示す名前、現在どうなっているかを示す状態が必要です。

aria-labelは名前を与える方法の一つですが、目に見えるラベルがある場合は、そのラベルと読み上げ名が食い違わないようにします。

動的な更新をすべて読み上げさせない

aria-liveは、操作後に別の場所で変わった結果など、フォーカスを移さず知らせる必要がある更新に使います。

装飾的な変化や頻繁な更新まで通知すると、必要な情報を聞き取りにくくなります。

表示とARIAの状態を同じ処理で更新する

パネルを開いたのにaria-expanded='false'が残ると、見た目と読み上げが矛盾します。

クラス名、表示状態、ARIA属性を別々の処理で変更せず、一つの状態を基に更新するとずれを防ぎやすくなります。

実装後のテスト手順

自動検査だけでは、操作の自然さや読み上げの文脈までは確認できません。

次の順序で手動確認と自動検査を組み合わせます。

  1. キーボードだけで操作する:すべての機能へ到達でき、フォーカスが消えたり閉じ込められたりしないか確認します。
  2. フォーカス表示を見る:通常時、ホバー時、フォーカス時を区別できるか確認します。
  3. スクリーンリーダーで確認する:名前、役割、開閉状態、選択状態、エラーが意図どおり伝わるか確認します。
  4. 拡大して確認する:文字や画面を拡大しても、操作部品や内容が重ならず利用できるか確認します。
  5. 色とコントラストを確認する:文字、境界、フォーカス表示を識別でき、色だけで状態を伝えていないか確認します。
  6. 自動検査を行う:ラベル不足、属性の不整合、コントラストなど、機械的に見つけやすい問題を補足します。

複雑な部品を作る場合は、WAI-ARIA Authoring Practicesのデザインパターンで、役割とキーボード操作を照合します。

公開前のチェックリスト

カスタムUIは状態と操作から設計する

アクセシブルなカスタムUIは、ARIA属性の数ではなく、利用者の操作とコンポーネントの状態が一貫して伝わるかで評価します。

標準要素を出発点にし、独自実装が必要な箇所だけを補い、キーボードと支援技術で確かめる流れを設計とレビューに組み込んでください。

モバイルバージョンを終了