トピックを検索
リンクと読み上げられ、Spaceキーで押せないボタン
フォームを開く丸いボタンを、href="#"のリンクで作っています。そのためスクリーンリーダーはリンクと読み上げ、Spaceキーではボタンが押されずにページがスクロールします。
<a href="#" class="pill"> 問題
スクリーンリーダーの利用者は、フォームを開く操作要素を、別のページへ移動するリンクだと伝えられます。キーボード利用者がSpaceを押すと、ボタンは押されずにページがスクロールします。
あるお店の商品ページに、売り切れになったリネンのトートバッグが表示されています。価格の下には、深緑の丸いボタン「再入荷のお知らせ」があります。押すと、メールアドレスを入力する小さなフォームがページの上に開きます。見た目はボタンで、働きもボタンです。その場で何かを開くだけで、どこへも移動しません。
ところが、作りはリンクです。キーボード利用者がTabで丸いボタンへ移動し、ボタンを押すつもりでSpaceを押すと、ページが1画面分下へスクロールします。丸いボタンは画面の外へ流れ、フォームは開きません。Enterなら開きます。スクリーンリーダーの利用者には「再入荷のお知らせ、リンク」と聞こえます。リンクは別のページへ移動するものなので、この商品ページから離れると思い込みます。入荷の連絡を受け取る方法をページのボタン一覧から探しても、見つかりません。この操作要素は、リンク一覧のほうに入っているからです。
達成基準4.1.2「名前(name)・役割(role)及び値(value)」は、支援技術が操作要素の種類を伝えられるよう、すべての操作要素の役割(ロール)をコードから判別できることを求めています。href を持つ a 要素は、ブラウザーにとってリンクであり、スクリーンリーダーにもリンクというロールを渡します。フォームを開くクリック処理を加えても、丸いボタンの見た目にするクラスを付けても、ロールは変わりません。そのため、コード上のロールはリンクのままで、働きだけがボタンです。ARIA Authoring Practicesも、ボタンが行う操作はリンクの機能とはっきり異なり、ウィジェットの見た目とロールはどちらも、その機能に合わせるべきだと述べています。
キー操作もロールに従います。ブラウザーはリンク上のEnterをクリックとして扱いますが、リンク上のSpaceはページをスクロールするキーです。そのため、Spaceではクリック処理が実行されません。HTML標準のボタンなら、EnterでもSpaceでもクリック処理が実行されます。href="#" は、リンクにフォーカスが当たるようにし、ページの再読み込みを防ぐためだけに付けられていますが、この値にも別の落とし穴があります。「リンクを新しいタブで開く」を選ぶと同じページの複製が開き、スクリプトの読み込みが遅れていると、押したときにページの先頭へ飛びます。
マウスでもEnterでも動くため、簡単な確認では問題が見つかりません。問題が表に出るのは、操作要素が何と読み上げられるかを頼りにする人と、ボタンをSpaceで押す人だけです。
10グループ中2グループに影響
axeのようなルールベースの自動チェックには、名前とアドレスのあるリンクとしか見えないため、何も報告されません。フォームを開くリンクも、リンクとしては正しいからです。その操作要素が何をするかは、実際に押すまで分かりません。EaseWebの診断は、どこも指していないリンク(href="#"、"#!"、""、javascript: URL)を、人が押して確かめる対象として一覧にします。ただし、実在するアドレスを持ちながら、スクリプトでフォームを開くリンクは、問題がないように見えます。コード生成AIが手軽な修正として提案することのある role="button" の追加は、読み上げを変えるだけで、Spaceによるスクロールは残ります。
試してみる
Tabで「再入荷のお知らせ」へ移動してSpaceを押し、次にEnterを押してください。
Spaceでフォームが開きますか? それともページがスクロールしますか? 下の欄に、スクリーンリーダーがこのボタンをリンクと読むか、ボタンと読むかが出ます。
問題あり 修正できますか?
このバッグについて
洗うたびに柔らかくなる、洗いをかけたリネンの大きめのトートです。内ポケットに畳んで収まるので、どこへでも持ち歩けます。
- 洗いをかけたリネン、40×38 cm
- ファスナー付きの内ポケット
- 肩に掛けられる長い持ち手
配送と返品
60ドル以上のご注文で送料無料です。30日以内なら、届いたときの包装のままで無料で返品できます。
お手入れ
洗濯機の冷水で洗い、吊るして乾かしてください。中温のアイロンで、張りのある風合いに戻ります。
スクリーンリーダーの読み上げ:
(Tabで丸いボタンへ移動)
修正方法
操作のための要素はbuttonで作るか、リンクにrole="button"を付けてSpaceで押せるようにします。
- 1何かを開く・変える・送る操作要素はbuttonのロールにし、リンクはアドレスへの移動に使う。
- 2EnterでもSpaceでも1回だけ押され、Spaceでページがスクロールしない。
- 3どの要素で作っても、丸いボタンの見た目は変えない。
<p class="stock">売り切れ</p><a href="#" class="pill notify"> 再入荷のお知らせ</a><dialog id="notify" aria-labelledby="notify-title"> …</dialog>Button要素を使う
<p class="stock">売り切れ</p><button type="button" class="pill notify"> 再入荷のお知らせ</button><dialog id="notify" aria-labelledby="notify-title"> …</dialog>この方法を選ぶ理由:まずHTMLの要素を使う
<a href="#" role="button" class="pill notify"> 再入荷のお知らせ</a>丸いボタンは a 要素なのでリンクになり、働きだけをスクリプトでボタンにしています。スクリーンリーダーはリンクと伝え、ボタンなら押せるはずのSpaceでは、ページがスクロールします。href="javascript:void(0)" のリンクや、アドレスは実在してもスクリプトが毎回移動を取り消すリンクも同じです。
button要素はボタンとして読み上げられ、ブラウザーはEnterでもSpaceでもクリック処理を実行します。キー操作の処理は不要で、ページがスクロールすることもありません。type="button" を付けると、フォームの中に置いても、そのフォームを送信しません。CSSでブラウザー標準の枠線と灰色の背景を取り、フォントを指定すれば、丸いボタンの見た目は元のままです。
role="button" を付けると、スクリーンリーダーは「ボタン」と読み上げるので、ロールの問題は直ります。しかし、ARIAが変えるのは読み上げだけです。ブラウザーにとってはリンクのままで、Spaceを押すとページがスクロールします。スクリーンリーダーの利用者はボタンだと伝えられるのに、どのボタンでも使えるはずのキーが効きません。上の2つ目の修正は、残りを手作業で補ったものです。HTML標準のボタンなら、その手間はいりません。
どちらの方法でも基準を満たします。button要素を使ってください。ロールも両方のキーもブラウザーが受け持つため、コードが少なく、失うものもありません。実在しないアドレスについて説明する必要もありません。role="button" とSpaceの処理を加えたリンクは、要素を変えられない場合に限って使い、テーマやプラグインを更新するたびにキー操作を確認し直してください。
見た目とロールは揃えます。デザイン上必要なら、ボタンをリンクのような見た目にすることもできます。ただし、下線の付いた言葉はふつうリンクの見た目なので、目で見て操作する人には「どこかへ移動する」ように見えます。そのためAuthoring Practicesは、操作要素の働きに合わせて見た目を調整することを勧めています。丸いボタンやボタンの形なら、その場で何かをする要素だと誰にでも伝わります。
この問題は、共通のコンポーネントから始まることがよくあります。href を渡されたときだけ a を、それ以外は button を出力する Button コンポーネントなら、2つを分けられます。いつも a を出力するものや、フォーカスを当てるために href="#" を渡すものでは、すべての操作がリンクになります。ルーターのリンクコンポーネントを操作に使った場合も同じです。
かごに入れる、購読するなど、サーバー側で何かを変える操作も、操作内容をアドレスに含めたリンクではなく、ボタンにします。リンクは先読み、ブックマーク、共有の対象になり、もう一度開くと同じ操作が繰り返されてしまうからです。送信ボタンのあるフォームで送るか、ボタンのクリック処理からサーバーを呼び出してください。
押した後の動作は別の課題です。showModal() で開いたHTML標準の dialog は、フォーカスをフォームの中へ移し、閉じるとボタンへ戻します。ほかの方法で作るダイアログについては、背後にフォーカスが残るモーダルを参照してください。
AI コーディングアシスタントで修正しますか? このガイドを Markdown で取得、または全ガイドをコーディングエージェントで使う。
修正の確認
マウスを使わない4つの確認
確認方法: キーボード、スクリーンリーダー
OS、ブラウザーと支援技術のバージョン、ビルド、実施日、各手順の実際の結果を記録してください。共通のボタンやリンクのコンポーネントを変更した際は、再度確認します。
制限
このガイドが扱うのは、ボタンの働きをするリンクです。逆に、別のページへ移動するだけのボタンは、ボタンとして読み上げられ、新しいタブで開くこともリンク一覧で見つけることもできません。同じトピックを反対側から見た問題で、今後のガイドで扱う予定です。ロールのないdivやspanにクリック処理を設定した場合は、Tabキーで到達できないdivのボタンを参照してください。ページをその場で絞り込んだり並べ替えたりするリンクは、ページを更新するリンクのトピックで扱います。言葉のないボタンについては、名前がないアイコンだけのボタンを参照してください。対象とする支援技術で、操作全体を確認してください。
よくある問題を再現した学習用のサンプルです。実在のクライアントの診断結果ではありません。コードは出発点となる実装例のため、実際の製品でも確認してください。ここでは支援技術でのテスト結果は報告していません。
コードを更新しても、使いやすさを保つために
ガイドの内容を、コーディングエージェントやCIで使える開発ルールにまとめます。更新後は、キーボードとスクリーンリーダーで再テストし、問題が再発していないか確認します。