focus-not-removed-by-script

スクリプトで、フォーカスを受け取った要素からフォーカスを外してはいけません

automaticWCAG 2.1.1, 2.4.7 (AA)確度:medium重大度:seriousoperable

インラインのonfocusハンドラーが自身に対してblur()を呼ぶだけの、タブ順序に含まれる要素をfailにし、blur()や別の要素に対するfocus()を呼ぶほかのハンドラーについて確認を求めます。これらは、要素がフォーカスを受け取った直後にフォーカスを外す可能性があります(WCAGの失敗例F55)。

適用範囲:フォーカスを受け取れ、ページがレンダリングしていて、インラインのonfocusハンドラーがblur()、または別の要素に対するfocus()を呼ぶ要素です。そうした要素がない場合や、どの要素もフォーカスを受け取れない文書では、適用対象はありません。

期待される結果:WCAGの失敗例F55:要素がフォーカスを受け取ったときにそこからフォーカスを外すスクリプトがあると、キーボードのユーザーはその要素に到達することも操作することもできず、フォーカスがどこにあるかもわかりません。

  • FOCUS_HANDLER_BLURS_SELF:タブ順序に含まれる要素で、ハンドラーがそれだけを行う場合(this.blur()、blur()、または名前か角かっこで指定したevent.targetやevent.currentTargetに対するblur()。if (this.blur)の後ろにあってもよく、ほかにあるのはreturnだけ)はfailです。F55の例がこれにあたります。フォーカスはどこにも行かず、ほかへ送られるのではなく失われます。タブ順序の外(tabindex="-1")では、キーボードのユーザーが到達しないため、確認を求めます。

それ以外の要素については、それぞれ確認を求めます(cantTell)。

  • ほかのコードと一緒にblur()を呼ぶ場合、または別の要素に対して呼ぶ場合はFOCUS_HANDLER_CALLS_BLURです。フォーカスが失われるかどうかはスクリプト次第です。
  • 別の要素に対してfocus()を呼ぶ場合(document.body.focus())はFOCUS_HANDLER_MOVES_FOCUSです。F55のテストが確認するとおり、フォーカスが届いた途端にそれを奪います。

フォーカスをどこかへ送るハンドラー(フォーカストラップの番兵要素、リダイレクト)は移動のケースであり、確認を求めるだけで、failにはしません。このルールが読むのはハンドラーのテキストであり、ページの実際の動作ではありません。人がその要素までTabキーで移動すれば確認できます。

検出結果が報告する内容:

  • reasonCode:FOCUS_HANDLER_BLURS_SELF、FOCUS_HANDLER_CALLS_BLUR、FOCUS_HANDLER_MOVES_FOCUSのいずれかです。
  • handler:onfocus属性の値で、空白をまとめ、最大120文字です。それより長いものは切り詰められ、…で終わります。
  • tabbable:要素がタブ順序に含まれるかどうかです。含まれない要素も、クリックやスクリプトからフォーカスを受け取ることはあります。

これらのdata.detailsのフィールドは、検出結果を読み解き、再現するのに役立ちます。reasonCodeと、出力スキーマで安定と明記された一部のフィールドを除き、安定した契約ではありません。マイナーリリースで名前が変わったり、なくなったりすることがあるため、これらに依存した実装はしないでください。

例

fail
<a href="/offers" onfocus="this.blur()">Offers</a>

リンクはフォーカスを受け取るとすぐに自身からフォーカスを外します。WCAGの失敗例F55自身の例です。キーボードのユーザーは、リンクにとどまってそれをたどることができません。

can't tell
<button type="button" onfocus="if (locked) this.blur(); track('focus')">Send</button>

ハンドラーはほかのコードと一緒にblur()を呼ぶため、フォーカスが失われるかどうかはスクリプト次第です。

n/a
<span onfocus="this.blur()">Label</span>

<span>はフォーカスを受け取れないため、そのハンドラーが実行されることはありません。

確認方法

このルールが判断できない場合はcantTellを報告し、判断を人に委ねます。ルールが投げかける各質問を、理由コードごとに、答えるための手順とともにここに示します。検出結果にも同じ手順がhowToCheckとして、スキャンの言語で含まれます。出力スキーマを参照してください。

FOCUS_HANDLER_BLURS_SELF

  1. レポートに示された要素のすぐ手前をクリックし、フォーカスが要素に届くはずのところまでTabキーを押してください(タブ順序にない場合は、代わりに要素をクリックしてください)。
  2. フォーカスインジケーターを観察し、開発者ツールのコンソールでdocument.activeElementを確認してください。
  3. もう一度Tabキーを押し、フォーカスがどこへ移るかを確認してください。

満たす場合:フォーカスは要素にとどまってフォーカスインジケーターが表示され、次のTabキーで次のコントロールへ移ります。

満たさない場合:フォーカスが要素に届いた途端に消えるため、キーボードで到達または操作できず、WCAG 2.1.1と2.4.7を満たしません(F55)。

FOCUS_HANDLER_CALLS_BLUR

  1. レポートに引用されたonfocusハンドラーを読み、いつ、どの要素に対してblur()を呼んでいるかを控えてください。
  2. 要素のすぐ手前をクリックし、フォーカスが届くはずのところまでTabキーを押してください。ハンドラーが判定するそれぞれの状態(たとえばフィールドが入力済みか空か)で繰り返してください。
  3. フォーカスインジケーターを観察し、開発者ツールのコンソールでdocument.activeElementを確認してください。
  4. キーボードで要素を操作してみてください(入力する、EnterまたはSpaceを押す)。

満たす場合:どの状態でもフォーカスは要素にとどまってフォーカスインジケーターが表示され、キーボードで操作できます。

満たさない場合:ある状態では要素がフォーカスを受け取った途端にフォーカスが外されるため、キーボードで操作できないか、フォーカスが見えなくなり、WCAG 2.1.1と2.4.7を満たしません(F55)。

FOCUS_HANDLER_MOVES_FOCUS

  1. レポートに引用されたonfocusハンドラーを読み、どの要素へフォーカスを送っているかを控えてください。
  2. 要素のすぐ手前をクリックし、フォーカスが届くはずのところまでTabキーを押して、フォーカスがどこに移るかを確認してください(コンソールでdocument.activeElementを確認します)。
  3. 要素が、ダイアログの端にあってフォーカスを内側に戻す、見えない名前のない番兵要素であれば、それはモーダルのためのフォーカストラップであり想定どおりであることを控えてください。
  4. それ以外の場合は、キーボードで要素を操作してみて、Shift+Tabで戻れるか確認してください。

満たす場合:フォーカスは適切な場所(ダイアログのフォーカスの循環)に移るか要素にとどまり、すべてのコントロールに引き続きキーボードで到達して操作できます。

満たさない場合:表示されているコントロールが、フォーカスが届いた途端に別の場所へフォーカスを送るため、キーボードで到達または操作できず、WCAG 2.1.1と2.4.7を満たしません(F55)。

ソースコードを見る