アクセシブルなWebボタンのための短く、実践的なチェックリスト
本番環境に届く前に、ボタンのアクセシビリティ問題の大半を見つける5つのルール
目次
ボタンのアクセシビリティ助言が抱える問題
ボタンのアクセシビリティに関するガイダンスの多くは、2つのどちらかに分かれます。誰も読まない40ページの WCAG 解釈か、実行可能な手順のない「ボタンをアクセシブルにする」という曖昧な提案です。木曜日に機能をリリースしようとしているとき、そのどちらも役に立ちません。
このチェックリストでは、本番環境でよく見られるボタンのアクセシビリティ不備のうち、最も一般的な5つを扱います。これで WCAG の専門家になれるわけではありませんが、実際にユーザーへ影響する問題は見つけられます。
1. ボタンには button 要素を使う
ボタンのように振る舞うものは、<button> 要素であるべきです。onclick を付けた <div> でも、role="button" を付けた <span> でも、href="#" と preventDefault を使った <a> でもありません。
<button> 要素を使えば、キーボードナビゲーション、フォーカス管理、スクリーンリーダーによる通知が最初から得られます。<div> を使うと、それらすべてを一から作り直すことになります。そして、たいていどこかで間違えます。
唯一の例外: その操作が新しいページへ移動する、または URL を変更する場合は、<a> 要素を使います。リンクとボタンは意味的に異なります。スクリーンリーダーのユーザーは要素の種類で移動するため、ボタンには操作の実行を、リンクには移動を期待します。
2. ヒットターゲットを少なくとも44×44ピクセルにする
WCAG 2.5.5 (Level AAA) は、インタラクティブな要素に対して最小44×44 CSS ピクセルのターゲットサイズを求めています。これは見た目のサイズではなく、クリックできる領域の話です。
見た目は小さなボタンでも十分な padding を持たせることはできますし、疑似要素でヒットターゲットを広げることもできます。重要なのは、ユーザーが正確に狙わなくてもよいことです。
モバイルユーザー、運動機能に制約のある人、移動中のデバイスを使っている人は、小さなターゲットを押し損ねます。24×24ピクセルのアイコンボタンは見た目にはすっきりしているかもしれませんが、ユーザビリティ上の失敗です。
3. ブラウザー既定だけに頼らない、見えるフォーカス状態を用意する
ブラウザー既定のフォーカスリングは何もないよりはましですが、ブラウザー間で一貫性がなく、背景によってはほとんど見えません。デザインシステムの中で機能するカスタムのフォーカス状態が必要です。
よいフォーカスインジケーターには、次の3つの性質があります。
- 高いコントラスト: 隣接する色に対して少なくとも3:1
- 見えるオフセット: ボタン自身の border や background に隠れない
- 一貫した形状: ユーザーがインターフェース全体でフォーカスインジケーターとして認識できる
よりよい代替を用意せずに outline: none を指定してはいけません。また、完璧な照明条件で自分にだけ見えるほどフォーカス状態を控えめにしてはいけません。
4. 文脈から切り離されても意味が通じるボタンラベルを書く
スクリーンリーダーのユーザーは、ボタン間をジャンプして移動することがよくあります。そのとき聞こえるのは、周囲の文脈がないボタンラベルの一覧です。
その一覧の中で「詳しく見る」というラベルは役に立ちません。「ここをクリック」や「送信」も同じです。ラベルは操作を説明するべきです。「アクセシビリティチェックリストをダウンロード」、「更新情報を購読」、「このコメントを削除」のようにします。
デザイン上、短い視覚ラベルが必要な場合は、aria-label を使って説明的な代替を提供します。ただし、よりよい解決策は、誰にとっても機能するラベルを書くことです。
アイコンのみのボタンでは、aria-label が必須です。虫眼鏡アイコンだけのボタンには、aria-label="Search" または同等のテキストが必要です。アイコンはスクリーンリーダーにとってアクセシブルではありません。
5. 十分なカラーコントラストを確保する
WCAG 2.1 は、通常テキストには少なくとも4.5:1、大きなテキスト(18pt または 14pt 太字)には3:1のコントラスト比を求めています。ボタンラベルは通常、通常テキストです。
白いボタン上の薄いグレーのテキストは不合格です。薄い青の背景に淡い青を載せるのも不合格です。こうした組み合わせは洗練されて見えるかもしれませんが、弱視、色覚特性のあるユーザー、または明るい日差しの中で画面を見ている人を排除します。
コントラストチェッカーは、ローンチ後ではなくデザイン時に使いましょう。本番環境でコントラスト問題を修正するのは高くつきます。多くの場合、デザインシステムの変更が必要になるためです。
画像処理ツールを扱っている場合、client-side processing can help preserve privacy while generating accessible visual assets — 特に色の組み合わせをテストしたり、プレビュー状態を生成したりするときに役立ちます。
このチェックリストで扱わないこと
このリストは意図的に不完全です。disabled 状態の意味、loading 状態、エラー処理、split button や dropdown trigger のような複雑なボタンパターンは扱いません。そうしたパターンには、それぞれ個別のガイダンスが必要です。
また、ボタンと他のインタラクティブ要素をいつ使い分けるべきかという、より広い問いも扱いません。そのためには、semantic HTML と accessibility tree を理解する必要があります。これらはそれぞれ単独の記事に値するテーマです。
ここで扱うのは、手を付けやすい成果です。ほぼすべてのコードレビューに現れ、最も多くのユーザーに影響し、開発中に最も修正しやすい誤りです。
このチェックリストをワークフローに組み込む方法
アクセシビリティチェックリストが機能するのは、後から付け足されるのではなく、開発プロセスの一部になっている場合だけです。そうするための方法は次のとおりです。
デザインで: フォーカス状態とヒットターゲットの注釈をデザインファイルに追加します。開発者が推測する余地として残さないでください。
コードレビューで: <button> 要素、アイコンボタンの aria-label、フォーカス状態の CSS を確認します。これらはすぐに見つけられます。
テストで: キーボードでインターフェースを Tab 移動します。ボタンに到達できない、またはフォーカス位置が見えないなら、ユーザーにも同じことが起きます。
ドキュメントで: コンポーネントライブラリにボタンのアクセシビリティ要件を含めます。間違ったことをするより、正しいことをする方が簡単な状態にします。
本番環境の問題をデバッグしている場合、tools for inspecting HTTP headers and redirects は、支援技術がマークアップをどのように解釈しているかを理解する助けになります。特に、ナビゲーション後のフォーカス管理を調査するときに有用です。
この作業を省くコスト
アクセシブルでないボタンは、単に WCAG 準拠に失敗するだけではありません。ワークフローを壊します。送信ボタンをクリックできないユーザーはフォームを完了できません。フォーカス状態が見えないユーザーはキーボードで移動できません。ボタンの文字と背景を区別できないユーザーはラベルを読めません。
これらはエッジケースではありません。世界人口のおよそ15%には何らかの障害があり、一時的な制約(壊れたマウス、強い日差し、赤ちゃんを抱いていること)は、いずれ誰にでも起こります。
幸いなことに、ボタンのアクセシビリティはほとんどが解決済みの問題です。新しいパターンを発明したり、ブラウザーサポートを待ったりする必要はありません。プラットフォームを正しく使い、自分の作業をテストするだけでよいのです。
重要なポイント
- ボタンには
<button>要素を、ナビゲーションには<a>要素を使う — 意味的な違いは支援技術にとって重要です - 運動機能に制約のあるユーザーやモバイルユーザーに対応するため、ヒットターゲットを少なくとも44×44 CSS ピクセルにする
- デザインシステム全体で機能する、見やすく高コントラストなフォーカス状態を用意する
- 単独で読まれても意味が通じるボタンラベルを書き、アイコンのみのボタンには
aria-labelを使う - 高コストな後付け修正を避けるため、ローンチ後ではなくデザイン時にカラーコントラストを確認する
FAQ
Q: キーボードハンドラーを追加すれば、<div> に role="button" を使ってもよいですか?
A: 使うことはできますが、使うべきではありません。Enter、Space、フォーカス管理、disabled 状態を手動で扱う必要があります。そして、どこかを必ず見落とします。<button> 要素は、これらを既定で正しく処理します。それを使ってください。
Q: 再生/一時停止ボタンのように、状態を切り替えるボタンはどうすればよいですか?
A: 現在の状態を示すために、aria-pressed="true" または aria-pressed="false" を使います。ボタンラベルも現在の状態ではなく、クリック時に起こる操作を反映するべきです(再生中なら「一時停止」、一時停止中なら「再生」)。スクリーンリーダーのユーザーが知る必要があるのは、システムが今どの状態にあるかではなく、そのボタンが何をするかです。
Q: disabled ボタンもコントラスト要件を満たす必要がありますか?
A: WCAG 2.1 は disabled controls をコントラスト要件(1.4.3)から除外していますが、これは議論のある点です。コントラストの低い disabled ボタンは、誰にとっても認識しにくいものです。disabled ボタンを表示するなら、読めるようにしてください。さらによいのは、非表示にするか、なぜ disabled なのかを説明することです。
Q: スクリーンリーダーなしでボタンのアクセシビリティをテストするにはどうすればよいですか?
A: キーボードを使います。インターフェースを Tab で移動し、すべてのボタンに到達できること、フォーカス位置が見えること、Enter または Space でボタンを起動できることを確認します。これで多くの問題を見つけられます。より深くテストするには、Chrome または Firefox DevTools の accessibility inspector を使って、計算された role と label を確認します。
Q: aria-label と aria-labelledby の違いは何ですか?
A: aria-label はテキスト文字列を直接提供します。aria-labelledby は、ラベルになるテキスト内容を持つ別の要素の ID を参照します。ラベルテキストがすでに DOM の別の場所に存在する場合は aria-labelledby を使います。画面上には表示されていないラベルを提供する必要がある場合は aria-label を使います。
Sources
- Web Content Accessibility Guidelines (WCAG) 2.1 — W3C
- Inclusive Components: Toggle Buttons — Heydon Pickering
- The ARIA Button Pattern — W3C ARIA Authoring Practices Guide
- WebAIM: Keyboard Accessibility — WebAIM


