トピックを検索
キーボードで開けず、閉じるボタンにも名前がないチャット
チャットの起動ボタンがクリック処理を付けたdivのためTabキーで届かないうえ、パネルの×もアイコンしかないボタンで、スクリーンリーダーには「ボタン」としか読まれない
<div class="chat-launcher"> 問題
キーボードの利用者がサポートチャットを開けず、スクリーンリーダーの利用者にはどのボタンでチャットを閉じるのかが伝わらない
家具の店Birchwood Homeのサイトでは、どのページの右下にも丸いチャットの吹き出しがあります。マウスの利用者がクリックすると、その場所にチャットのパネルが開きます。「Birchwoodのチャット」という見出し、閉じるための×、あいさつ、メッセージ欄です。キーボードの利用者がTabキーでページを下へ進むと、フォーカスは「配送料金」「注文の追跡」「返品」と移り、次のTabでページを離れてブラウザー自身のコントロールへ移ります。吹き出しには一度も届かず、フォーカスが届かないものはEnterキーでも開けません。別の方法でチャットを開いたスクリーンリーダーの利用者がTabキーで×へ移ると、「ボタン」と読まれるだけで、何をするボタンなのか、チャットを閉じるボタンなのかは分かりません。
吹き出しは、クリック処理を付けた div の中にアイコンを入れたものです。div はフォーカスを受け取らないため、Tabキーは素通りし、EnterキーもSpaceキーも効きません。達成基準2.1.1は、マウスでできることはすべてキーボードでもできることを求めていますが、ここでチャットを開けるのはマウスだけです。
達成基準4.1.2は、すべてのコントロールに、支援技術が読み取れる名前と役割があることを求めています。吹き出しにはどちらもありません。ボタンではなく、言葉もなく、絵があるだけです。×は本物の button なので役割はあり、Tabキーでも届きますが、中には文字のないアイコンしかないため名前が空で、スクリーンリーダーは「ボタン」とだけ読みます。横に「送信」ボタンもあるパネルでは、押してみないとどちらがどちらか分かりません。W3Cは、どちらも4.1.2の失敗例として挙げています。スクリプトでコントロールにした div に役割がないもの(F59)と、名前のないコントロール(F68)です。
チャットはどのページでも同じ隅にあり、困った人を案内する先になっていることも多いため、開けない人は、本来その人たちのために用意された助けを失います。
10グループ中2グループに影響
自動チェックから見ると、吹き出しはアイコンの入った div にすぎません。チャットを開く処理はスクリプトで追加されるため、マークアップにはその div がコントロールであることを示すものがなく、手がかりは、cursor: pointer の指の形のカーソルと、隅に固定された位置だけです。×の方は見つかりやすく、名前のないボタンはよくあるチェック項目です。ただし見つかるのはパネルが開いている間だけで、チャットのパネルの多くは、ページを開いた時点では閉じていて、開く操作がないかぎり閉じたままです。チャットウィジェットは提供元のスクリプトであることが多く、提供元のドメインのフレーム内に描かれることもあるため、サイト側のチームがそのコードを読むことはほとんどありません。チャットの吹き出しの実装をAIアシスタントに頼むと、クリックできる div を書くことがあります。マウスでは見た目も動作も同じだからです。
試してみる
キーボードだけでチャットを開いて閉じ、それぞれのボタンが何と読まれるか聞いてみましょう
Tabキーでページを下へ進んでください。フォーカスはチャットの吹き出しに届きますか?吹き出しをクリックしてチャットを開き、Tabキーで×へ移って、ページの下に出るスクリーンリーダーの読み上げを確かめます。
修正を適用して、すべてキーボードで試してください。
修正方法
起動ボタンと×をHTML標準のボタンにし、それぞれに言葉の名前を付ける
- 1チャットの起動ボタンは、Tabキーで届くHTML標準のボタンにする
- 2起動ボタンと閉じるボタンにはそれぞれ言葉の名前を付け、アイコンは読み上げから隠す
- 3チャットを閉じたら、フォーカスを起動ボタンに戻す
<div class="chat-launcher"> <svg class="icon" viewBox="0 0 24 24"> <use href="#icon-chat"></use> </svg></div><section id="chat" class="chat-panel" aria-labelledby="chat-title" hidden> <div class="chat-header"> <h2 id="chat-title">Birchwoodのチャット</h2> <button type="button" class="chat-close"> <svg class="icon" viewBox="0 0 24 24"> <use href="#icon-close"></use> </svg> </button> </div> <div class="chat-messages" role="log" aria-label="メッセージ"> <p class="message from-us">こんにちは。ご注文についてお気軽にお尋ねください。</p> </div> <form class="chat-form"> <label for="chat-input" class="visually-hidden">メッセージ</label> <input id="chat-input" autocomplete="off"> <button>送信</button> </form></section>丸いアイコンのまま、名前のあるボタンにする
<button type="button" class="chat-launcher" aria-label="チャットで相談"> <svg class="icon" viewBox="0 0 24 24" aria-hidden="true"> <use href="#icon-chat"></use> </svg></button><section id="chat" class="chat-panel" aria-labelledby="chat-title" hidden> <div class="chat-header"> <h2 id="chat-title">Birchwoodのチャット</h2> <button type="button" class="chat-close" aria-label="チャットを閉じる"> <svg class="icon" viewBox="0 0 24 24" aria-hidden="true"> <use href="#icon-close"></use> </svg> </button> </div> <div class="chat-messages" role="log" aria-label="メッセージ"> <p class="message from-us">こんにちは。ご注文についてお気軽にお尋ねください。</p> </div> <form class="chat-form"> <label for="chat-input" class="visually-hidden">メッセージ</label> <input id="chat-input" autocomplete="off"> <button>送信</button> </form></section>この方法を選ぶ理由:まずHTMLの要素を使う
div のクリック処理は、マウスでしか動きません。×は button ですが、中にはタイトルのない svg しかないため、名前がありません。closeChat() の launcher.focus() も div には効かず、フォーカスは body に戻ってしまいます。
起動ボタンは button になったので、Tabキーで届き、EnterキーでもSpaceキーでも押せます。押すと同じクリック処理が動き、チャットを閉じればフォーカスは起動ボタンに戻ります。aria-label で、起動ボタンに「チャットで相談」、×に「チャットを閉じる」という名前を付けたので、「チャットで相談、ボタン」「チャットを閉じる、ボタン」と読まれます。aria-hidden で、アイコンは読み上げの対象から外れます。スクリプトは変わりません。ボタンには div のときと同じクラスを付けているので、見た目もそのままです。ブラウザーの既定の枠線や背景が出る場合は、そのクラスで消します。各ボタンの中に視覚的に隠したテキストを入れても、同じように名前を付けられます。名前がないアイコンだけのボタンを参照してください。
どちらも、起動ボタンと×をTabキーで届くボタンにし、名前を付けるため、2.1.1と4.1.2を満たします。名前を隠す方法なら、丸い吹き出しのデザインをそのまま残せ、起動ボタンがページに重なるスマートフォンでも場所を取りません。名前を表示する方法は幅を取りますが、何のボタンかが誰にでも分かります。音声操作の利用者は隠れた名前を推測せずにボタンの言葉を言え、アイコンを知らない人は言葉を読めます。デザインに余裕があれば名前を表示し、吹き出しを小さく保つ必要があれば名前を隠す方法を選んでください。
多くのチャットウィジェットは提供元のスクリプトで、起動ボタンもパネルも、提供元のドメインのフレームの中に描かれることがよくあります。その場合、自社のCSSやスクリプトは中に届きません。できることは次のとおりです。
- 導入する前に、「修正の確認」の手順でウィジェットを試す。提供元のデモページか、自社のテスト用ページで行います。
- ウィジェットの設定を確認する。起動ボタンに文字のラベルを表示できるものや、ボタンの名前を設定できるものがあります。サイトで使うそれぞれの言語で、両方を設定します。
- 起動ボタンと閉じるボタンが名前のあるHTML標準のボタンか、どのスクリーンリーダーで試したかを、提供元に尋ねる。フレームのタイトルについても尋ねます(詳しくはタイトルがない、または中身の分からないiframeを参照)。
- うまくいかない点を、再現手順を添えて提供元に報告する。直るまでは、アクセシビリティ方針に既知の問題として記載し、チャットを案内しているページに、メールアドレスなど別の問い合わせ方法を示します。
提供元のスクリプトは、自社のリリースと関係なく変わります。提供元の更新やウィジェットの設定の変更のたびに、確認を繰り返してください。
divに role="button" を付けるだけでは足りない。 役割を付ければスクリーンリーダーは「ボタン」と読みますが、div のままではフォーカスを受け取らず、EnterキーにもSpaceキーにも反応しません。tabindex="0" と、両方のキーを扱う処理を自分で加える必要があります。HTML標準の button には、どれも最初から備わっています。役割だけでは修正にならない理由は、Tabキーで到達できないdivのボタンを参照してください。
何をするかで名付ける。 「チャットで相談」「ヘルプ」「質問する」は、押すと何が起きるかを伝えます。「チャットアイコン」「吹き出し」や提供元の製品名は伝えません。×は「チャットを閉じる」にし、「×」や「閉じるアイコン」にはしません。未読の返信の数を起動ボタンに表示する場合は、「チャットで相談、新着メッセージ1件」のように名前にも入れます。メッセージを読み上げないチャットウィジェットが、パネルを閉じている間に届いた返信について勧めている方法です。
最小化ボタンもあるパネル。 「最小化」と「閉じる」の二つのボタンを持つパネルもあります。名前のないアイコンが二つ並ぶと一つのとき以上に分からないため、それぞれ「チャットを最小化」「チャットを終了」のように、何をするかで名付けます。
起動ボタンの位置。 隅に固定された起動ボタンは、フォーカス中のコントロールを覆うことがあります。フォーカス中のボタンを一部隠すチャットボタンを参照してください。HTMLでフッターの後に置かれたパネルには、フォーカスが最後にしか届きません。フォーカス順の最後に回る、フローティングボタンとパネルを参照してください。フォーカスを中に留めたまま、Tabキーで届く閉じるボタンもEscapeキーもなく、キーボードでは出られないパネルは、キーボードトラップです。キーボードで閉じられないポップアップを参照してください。
修正の確認
5項目、マウス不要
確認方法: キーボード、スクリーンリーダー、音声入力
OS、ブラウザーと支援技術のバージョン、ビルド、実施日、各手順の実際の結果を記録してください。チャットウィジェット、その提供元のスクリプト、または設定を変更した際は、再度確認します。
制限
このサンプルは、ページ自身が描く起動ボタンとパネルのための出発点で、あらゆるウィジェットで同じ結果になることを保証するものではありません。提供元のウィジェットをそもそも変えられるかどうかは提供元によります。別のドメインのフレームの中にある場合、手を加えられるのは、ウィジェットの設定か、提供元への依頼だけです。チャットのメッセージの読み上げは別の問題で、メッセージを読み上げないチャットウィジェットで扱っています。ボットだけで担当者に連絡できないチャットについては、担当者につながらないサポートのチャットボットを参照してください。実際に利用者が使う支援技術で、操作全体を確認してください。
よくある問題を再現した学習用のサンプルです。実在のクライアントの診断結果ではありません。コードは出発点となる実装例のため、実際の製品でも確認してください。ここでは支援技術でのテスト結果は報告していません。
EaseWebのサービス
修正した問題を、次のリリースで再発させない
このガイドのような修正方法を、コーディングエージェントが従うルールと、CIのチェックに組み込みます。あわせて定期的に、キーボードとスクリーンリーダーで手動の再テストを行います。