トピックを検索
キーボードで打ち間違いを直せないワンタイムコードの入力欄
ワンタイムコードの入力欄がキーを離すたびにフォーカスを次の欄へ送るため、Shift + Tabで戻ってもすぐ先へ送り返されてしまい、打ち間違えた数字にキーボードで戻れない
box.addEventListener('keyup', …) 問題
キーボード、スイッチ、スクリーンリーダーの利用者は、1桁打ち間違えるとその桁に戻れず、正しいコードを送れない
あるショップは、ログインに2段階目の確認を設けています。6桁のコードをテキストメッセージ(SMS)で送り、1桁ずつの6つの欄を表示します。1つの欄が埋まるとフォーカスがすぐ次の欄へ移るので、Tabキーを押さずに続けて打てます。「Larkspurの確認コード:481902」というメッセージが届きます。4、8と打ち、間違えて7を打ちます。フォーカスはもう4つ目の欄にあります。
Backspaceを押しても何も起きません。4つ目の欄は空なので、消すものがないからです。Shift+Tabで戻ろうとすると、フォーカスは3つ目の欄に着いた途端、4つ目の欄へ戻ります。左矢印キーも効きません。マウスなら、7をクリックして消し、1を打てば済みます。キーボードでは、どのキーでも7に届きません。残るのは、間違いと分かっているコードを送るか、ページを離れてログインをやり直すことだけです。
達成基準2.1.1「キーボード」(レベルA)は、ページでできることをすべてキーボードでもできるよう求めています。このページでは、欄をクリックすればマウスで数字を直せます。それなら、キーボードでも直せなければなりません。
原因は、スクリプトが keyup を待っていることです。キーは押したときに働き、keyup のハンドラーは離したときに、その時点でフォーカスのある要素で動きます。Shift+Tabを押すと、フォーカスは3つ目の欄へ移ります。Tabを離すと、その keyup が3つ目の欄に届きます。欄には数字が入っているので、スクリプトはフォーカスを4つ目へ送ります。どのキーでも同じことが起きるため、数字の入った欄にとどまれるキーはありません。Backspaceと矢印キーは、フォーカスのある空の欄の中で働くだけで、前へ戻す処理はスクリプトにありません。Tabで先へ進めばこの欄から出られるので、キーボードトラップではありません。塞がれているのは、戻る道です。Chromium、Firefox、Safariのエンジンで、同じ動きを確認しました。
貼り付けられないワンタイムコードの入力欄のように、input イベントで次の欄へ移る欄は、Backspaceを扱っていなくても、このようにはなりません。input イベントは値が変わったときにだけ発生するため、Shift+Tabで3つ目の欄にとどまれます。ブラウザーはTabで着いた欄の数字を選択するので、1を打てば7と置き換わります。ほかの作り方の欄では、別の理由で同じことが起きます。div 要素で描き、ページ側のキーイベントのハンドラーで数字を入れる欄には、スクリプトで1つずつ加えない限り、入力欄が本来持つキー操作がありません。
ログイン用のコードは分単位で期限が切れることが多く、何度か間違えるとアカウントがロックされることもあります。直せない1桁は、打ち直しの手間だけでは済みません。
10グループ中2グループに影響
どの欄にもラベルがあるため、axeなどの自動チェックは合格にします。スクリプトがいつフォーカスを移すかは、マークアップには表れません。EaseWebの診断は、maxlength="1" の欄が4つ以上並んでいると、最初の欄から2桁を打ってShift+Tabを押し、フォーカスがすぐ3つ目の欄へ戻されたら ew:code-boxes-keyboard として報告します。打つのは2桁だけで、コード全体は打ちません。自動で送信されることがあるためです。input 要素でない欄は調べません。keyup で値の長さを maxlength と比べて次の欄へ移す書き方は、掲示板の回答やプラグインで以前から使われています。1回で正しく打てば問題なく動くため、正しく打つだけのテストでは何も見つかりません。
試してみる
4、8、7と打ってから、キーボードだけで7を1に直してみましょう
Backspace、左矢印キー、Shift+Tabを試してください。下に、キーごとのフォーカスの移り先が、途中で通った欄も含めて表示されます。
問題あり 修正できますか?
最後のキー:まだありません
修正方法
数字が入ったときだけ次の欄へ移るか、コードを1つの欄で受け取る
- 1次の欄へ移るのは数字が入ったときだけにし、キーごとには移らない
- 2打った数字のどれにもキーボードで戻れ、上から打ち直せるようにする
- 3デザインが許すなら、コードは1つの欄で求める
<p id="code-label">Enter the 6-digit code we sent to your phone</p><div class="code-boxes" role="group" aria-labelledby="code-label"> <input name="code-1" inputmode="numeric" maxlength="1" aria-label="Digit 1 of 6"> <input name="code-2" inputmode="numeric" maxlength="1" aria-label="Digit 2 of 6"> <input name="code-3" inputmode="numeric" maxlength="1" aria-label="Digit 3 of 6"> <input name="code-4" inputmode="numeric" maxlength="1" aria-label="Digit 4 of 6"> <input name="code-5" inputmode="numeric" maxlength="1" aria-label="Digit 5 of 6"> <input name="code-6" inputmode="numeric" maxlength="1" aria-label="Digit 6 of 6"></div><button type="submit">Continue</button>コード全体を受け取る1つの欄
<label for="code">Security code</label><p id="code-hint">Enter the 6-digit code we sent to your phone.</p><input id="code" name="code" type="text" inputmode="numeric" autocomplete="one-time-code" spellcheck="false" aria-describedby="code-hint"><button type="submit">Continue</button>この方法を選ぶ理由:まずHTMLの要素を使う
ハンドラーは、打った数字だけでなく、離されたすべてのキーで動きます。Shift+Tabで数字の入った欄に着くと、Tabキーの keyup がそこに届き、フォーカスはまた先へ移ります。キーボードでは、直したい数字の欄にとどまれません。
1つのテキスト欄なら、編集に使うキーはどれも、ふつうの入力欄と同じように働きます。Backspaceで7が消え、矢印キーでカーソルが動き、Shift+Tabで前の要素へ戻ります。フォーカスを移すものがないので、間違った方向へ移されることもありません。貼り付けたコードも丸ごと入り、autocomplete="one-time-code" に対応するブラウザーは、新しいメッセージのコードを候補に出せます。
3つとも、キーボードで数字を直せるようになります。1つの欄にしてください。スクリプトなしで役目を果たし、編集のキーも貼り付けもブラウザーが扱うため、保守するものがありません。keyup を input に変えるのは、公開中の欄をいちばん早く直す方法ですが、貼り付けの問題と、前へ戻らないBackspaceが残ります。最初の一歩と考えてください。デザインを変えられず欄に分けたままにする場合は、最後の方法のように、すべてのキーを使えるようにし、各欄が次の欄へ自動で進むことを欄のそばに書きます(「実装の判断」を参照)。
次の欄へフォーカスを移すのは、値が変わったときにだけ発生する input イベントにします。どのキーにも反応する keyup や keydown のハンドラーでは移しません。Tab、Shift、矢印キーでも動いてしまうからです。「欄が埋まっているか」を確かめても防げません。数字の入った欄にShift+Tabで着いたときこそ、問題が起きる場面だからです。
ブラウザーは、TabやShift+Tabで着いた欄の中身を選択します。小さな修正で上から打ち直せるのはこのためです。クリックで着いた場合はカーソルが置かれるだけで、ChromiumとFirefoxではスクリプトの focus() でも同じです。maxlength="1" の欄では、数字の横に打った数字は拒まれます。最後の方法は、フォーカスが来たときに数字を選択し、input のハンドラーで打ったばかりの数字だけを残します。そのため、どう着いても打てば置き換わります。Safariのエンジンではクリックで選択が解除されますが、それでも置き換わります。
欄に分ける2つの修正は、今もフォーカスを自動で移します。フォーカスの移動は、3.2.2 入力時の「状況の変化」に当たります。Understanding文書には、自動で次の欄へ進む分割された電話番号の欄の例がありますが、基準を満たすのは、フォームの冒頭でその動きを説明しているからです。欄の上の説明に「入力すると、自動で次の欄に進みます」のように書いてください。1つの欄なら何も移らないので、これも1つの欄を選ぶ理由です。
コードは、ボタンかEnterキーで利用者が送るようにします。最後の欄が埋まった瞬間に送信するフォームは、頼まれずにページを変えることになり、操作するだけでページが変わるドロップダウンと入力欄で説明している問題に当たります。打ち間違えた数字は、直す間もなく1回の失敗として数えられてしまいます。
日本語の入力方式(IME)では、数字が全角で入ることがあります。\D は全角数字も取り除くため、0〜9だけを残す欄は、理由も示さずに空のままになることがあります。全角数字を受け付けず、理由も示さない入力欄で説明しているとおり、先に半角に変換してください。
修正の確認
4項目
確認方法: キーボード、スクリーンリーダー、マウス
OS、ブラウザーと支援技術のバージョン、ビルド、実施日、各手順の実際の結果を記録してください。ログインの流れやコードの部品を変更した際は、再度確認します。
制限
このサンプルは、どのコードの入力でも同じ結果になることを保証するものではありません。例はログイン用のコードです。PIN、ギフトカードの番号、予約番号などを欄に分けて求める場合も、同じように確かめてください。コード全体の貼り付けは、貼り付けられないワンタイムコードの入力欄で扱っています。input でない要素で作った欄は、すべてのキーをスクリプトで加える必要があり、スクリーンリーダーが入力欄として扱わないこともあります。このガイドでは、そのコードは扱いません。利用者が頼るキーボード、スイッチ、スクリーンリーダーで、ログイン全体を確認してください。
よくある問題を再現した学習用のサンプルです。実在のクライアントの診断結果ではありません。コードは出発点となる実装例のため、実際の製品でも確認してください。ここでは支援技術でのテスト結果は報告していません。
EaseWebのサービス
修正した問題を、次のリリースで再発させない
このガイドのような修正方法を、コーディングエージェントが従うルールと、CIのチェックに組み込みます。あわせて定期的に、キーボードとスクリーンリーダーで手動の再テストを行います。