click-handler-keyboard-operable
ネイティブのコントロールでない要素のクリックハンドラーは、キーボードで動作する必要があります
クリックハンドラー(インラインのonclick、またはリスナーフックが確認したclickのリスナー)を持つ、ネイティブのコントロールでない要素が、キーボードフォーカスを受け取れ、その要素、祖先または子孫にあるキーのハンドラーがそのキー入力を受け取ることを確認します。キーボードのユーザーが、クリックで実行されるものを実行できるようにするためです。
適用範囲:ページがレンダリングする要素のうち、空でないインラインのonclick属性を持つもの、またはページがリスナーフック(listenerHookScript)を実行している場合は、要素自身にスクリプトからclickのリスナー(addEventListener('click', …)またはonclickプロパティ)が追加されているものです。ただし、次のものは除きます。
<html>と<body>。そこでのクリックハンドラーはページ全体のためのものです。- 何もしない文(
return false、void(0)、void 0、event.preventDefault())だけでできたハンドラー。何の機能も提供しません。 - 要素自身または祖先に
aria-disabled="true"がある要素。無効なコントロールは、操作する機能を提供しません。 - ネイティブのコントロール。それ自体のキーボードの動作がユーザーに届きます。
hrefを持つリンクやarea、button、hidden以外のinput、select、textarea、option、summary、label(ラベルが有効にするコントロールは、それ自体がフォーカスを受け取ります)、iframe、embed、controlsを持つaudioやvideo、そして編集ホスト(contenteditable)です。 - フラットツリーで(シャドウルートとスロットに割り当てられたコンテンツを含めて)、キーボードで有効にすると
clickを発生させるコントロール(hrefを持つリンクやarea、button、summary、またはtypeがbutton、submit、reset、image、checkbox、radioのinput)で、タブ順序に含まれるものを含む要素。コントロールのclickがハンドラーまでバブリングするため、これはイベントの委譲であり、キーボードですでに実行できます。 - フォーカスを受け取れず、受け取れる子孫もなく、ウィジェットのロールも
cursor: pointerもない要素。クリックできることを示すものが何もなく、そうしたハンドラーはクリックを記録するか、その伝播を止めるだけのことが多いためです。
期待される結果:キーボードのユーザーが、クリックで実行されるものを実行できます。ChromiumがEnterやSpaceでclickを発生させるのはネイティブのコントロールだけです。<span role="button" tabindex="0" onclick>はフォーカスを受け取りますが、どちらのキーでも何も起きません。
- 要素またはそのフラットツリーの子孫のいずれかがタブ順序に含まれ、インラインのキーのハンドラー(
onkeydown、onkeyup、onkeypress)が要素自身、祖先、または子孫にあるため、フォーカスされた要素からのキーイベントがいずれかに届く場合:pass。 - 要素または子孫がタブ順序に含まれるが、インラインのキーのハンドラーがない場合:cantTell(
CLICK_HANDLER_NO_KEY_HANDLER)。EnterとSpaceでクリックと同じことが起きるかを確認してください。 - 要素または子孫がフォーカスを受け取れるのは
tabindex="-1"によってだけで、祖先にキーのハンドラーがない場合:cantTell(CLICK_HANDLER_NOT_IN_TAB_ORDER)。Tabキーでは到達しませんが、ロービングtabindexのように、スクリプトがフォーカスをそこへ移す可能性があります。 - リスナーフックを使う場合は、スクリプトから要素または子孫に追加されたキーのリスナーも、インラインのキーのハンドラーと同じように数えます。祖先、要素を含むシャドウルート、document、windowにだけあるリスナーは、その要素のキーを処理するのか、ほかの要素のキーだけを処理するのかわかりません:cantTell(
CLICK_HANDLER_KEY_LISTENER_ABOVE)。 - 要素がタブ順序に含まれ、ロールがbutton、link、checkbox、switch、tab、menuitem、menuitemcheckbox、menuitemradioのいずれかであり、ページのスクリプトより前に組み込まれたフックが、要素自身、子孫、祖先、要素を含むシャドウルート、document、windowのどこにもキーのリスナーを確認せず、インラインのキーのハンドラーもない場合:fail(
CLICK_HANDLER_NO_KEY_LISTENER)。キーイベントがハンドラーに届かないため、EnterとSpaceでは何も起きません。ただし、focusまたはfocusinのリスナーが要素自身、祖先、要素を含むシャドウルート、document、windowにある場合は別です。要素がフォーカスを受け取った時点でキーのリスナーを追加する可能性や、タブであればフォーカス時にパネルを表示する可能性があるため、cantTell(CLICK_HANDLER_FOCUS_LISTENER)です。 - 要素も子孫もフォーカスを受け取れず、ロールがbutton、link、checkbox、switchのいずれかである場合:fail(
CLICK_HANDLER_CONTROL_NOT_FOCUSABLE)。要素はコントロールであると示しているのに、Tabキーでは到達しません。スクリプトによるリンクについてのWCAGの失敗例F42と同じです。ただし、祖先がaria-activedescendantやインラインのキーのハンドラーを持つ場合、またはフォーカス可能な複合ウィジェット(grid、treegrid、listbox、menu、menubar、tree、tablist、toolbar、radiogroup、combobox)である場合は、フォーカスを移さずに操作できる可能性があるため、cantTellです。 - 要素も子孫もフォーカスを受け取れず、ほかのウィジェットのロールまたは
cursor: pointerを持つ場合:cantTell(CLICK_HANDLER_NOT_FOCUSABLE)。comboboxのリストのoptionやgridのセルは、フォーカスを保つ要素から操作されることが多く、その操作がページのほかのコントロールで提供されている可能性もあります。
検出結果が報告する内容:
role:要素のARIAのロールで、ない場合は''です。focusable:要素自体がフォーカスを受け取れるかどうかです。
これらのdata.detailsのフィールドは、検出結果を読み解き、再現するのに役立ちます。reasonCodeと、出力スキーマで安定と明記された一部のフィールドを除き、安定した契約ではありません。マイナーリリースで名前が変わったり、なくなったりすることがあるため、これらに依存した実装はしないでください。
例
<span role="button" tabindex="0" onclick="save()" onkeydown="if (event.key === 'Enter' || event.key === ' ') save()">Save</span>
spanはフォーカスを受け取り、そのキーのハンドラーはクリックと同じ操作を実行します。
<div role="button" onclick="openPanel()">Open the panel</div>
要素はボタンであると示し、クリックハンドラーを実行しますが、キーボードフォーカスがそこに届くことはありません。
<span role="button" tabindex="0" onclick="showPreferences()">Manage my cookies</span>
spanはフォーカスを受け取りますが、EnterやSpaceではclickが発生せず、インラインのキーのハンドラーもありません。スクリプトから追加されたリスナーは、マークアップには現れません。
確認方法
このルールが判断できない場合はcantTellを報告し、判断を人に委ねます。ルールが投げかける各質問を、理由コードごとに、答えるための手順とともにここに示します。検出結果にも同じ手順がhowToCheckとして、スキャンの言語で含まれます。出力スキーマを参照してください。
CLICK_HANDLER_FOCUS_LISTENER
- レポートに示された要素をクリックし、何が起こるかを控えてください。
- ページを再読み込みし、要素にフォーカスが移るまでTabキーを押してください。
- Enter、次にSpaceを押し、クリックしたときの動作と比べてください。
- ここでキーボードで操作できない場合は、クリックで行えることを、ページの別の場所にあるボタンやメニュー項目など、キーボードだけで使える別の方法で行えるか確認してください。クリックで行えることをすべて行える場合にだけ、それを認めます。
満たす場合:Enter(ボタン型のコントロールではSpaceも)でクリックと同じことができるか、タブではフォーカスを移すだけでパネルが表示されるか、クリックで行えることをキーボードだけで使える別の方法で行えます。
満たさない場合:フォーカスが届いてもEnterやSpaceを押して何も起こらず、クリックで行えることを別の方法でもキーボードで行えないため、WCAG 2.1.1を満たしません(F54)。
CLICK_HANDLER_KEY_LISTENER_ABOVE
- レポートに示された要素をクリックし、何が起こるかを控えてください。
- 要素にフォーカスが移るまでTabキーを押してください。
- Enter、次にSpace(グループ内にある場合は矢印キーも)を押し、クリックと比べてください。
- ここでキーボードで操作できない場合は、クリックで行えることを、ページの別の場所にあるボタンやメニュー項目など、キーボードだけで使える別の方法で行えるか確認してください。クリックで行えることをすべて行える場合にだけ、それを認めます。
満たす場合:Enter(ボタン型のコントロールではSpaceも)でクリックと同じことができるか、クリックで行えることをキーボードだけで使える別の方法で行えます。
満たさない場合:要素でEnterやSpaceを押しても何も起こらず、上位のリスナーは処理しておらず、クリックで行えることを別の方法でもキーボードで行えないため、WCAG 2.1.1を満たしません。
CLICK_HANDLER_NOT_FOCUSABLE
- レポートに示された要素をクリックし、クリックで何が行われるかを控えてください。
- Tabキーでページ内を移動し、要素がフォーカスを一度も受け取らないことを確認してください。
- リスト、グリッド、またはcomboboxの項目であれば、そのウィジェットにフォーカスを移して矢印キーを使い、項目がアクティブになりEnterで操作が実行されるか確認してください。
- それ以外の場合は、同じことを行うキーボードで操作可能な別のコントロールがページにないか探してください。
満たす場合:管理するウィジェットまたは別のコントロールを通じて、同じ操作をキーボードで行えます。
満たさない場合:その操作はマウスでしか行えないため、WCAG 2.1.1を満たしません(F54、F42)。
CLICK_HANDLER_NOT_IN_TAB_ORDER
- レポートに示された要素をクリックし、何が起こるかを控えてください。
- Tabキーでページ内を移動し、フォーカスがその要素に移ることがあるか確認してください。
- グループ(タブ、メニュー、ツールバー、リスト)の一部であれば、Tabキーでグループに入り、矢印キーでその要素にフォーカスが移るか確認してください。
- フォーカスが移ったらEnterまたはSpaceを押し、クリックと比べてください。
- ここでキーボードで操作できない場合は、クリックで行えることを、ページの別の場所にあるボタンやメニュー項目など、キーボードだけで使える別の方法で行えるか確認してください。クリックで行えることをすべて行える場合にだけ、それを認めます。
満たす場合:キーボード(Tabキー、またはグループ内の矢印キー)で要素に到達でき、EnterまたはSpaceでクリックと同じことができるか、クリックで行えることをキーボードだけで使える別の方法で行えます。
満たさない場合:どのキーでも要素にフォーカスが移らず、クリックで行えることを別の方法でもキーボードで行えないため、その操作はマウス専用であり、WCAG 2.1.1を満たしません。
CLICK_HANDLER_NO_KEY_HANDLER
- レポートに示された要素をクリックし、何が起こるかを控えてください。
- ページを再読み込みし、要素にフォーカスが移るまでTabキーを押してください。
- Enter、次にSpaceを押し、クリックしたときの動作と比べてください。
- ここでキーボードで操作できない場合は、クリックで行えることを、ページの別の場所にあるボタンやメニュー項目など、キーボードだけで使える別の方法で行えるか確認してください。クリックで行えることをすべて行える場合にだけ、それを認めます。
満たす場合:Enter(ボタン型のコントロールではSpaceも)でクリックと同じことができるか、クリックで行えることをキーボードだけで使える別の方法で行えます。
満たさない場合:EnterやSpaceを押しても何も起こらないかクリックより少ないことしか起こらず、クリックで行えることを別の方法でもキーボードで行えないため、WCAG 2.1.1を満たしません(F54)。