トピックを検索
入力した番号や貼り付けた番号が変わってしまう入力マスク
電話番号欄の入力マスクには数字の枠が10個しかないため、先頭に+1を付けて貼り付けた番号が別の番号に変わり、空いた枠の並びも欄の値として読み上げられてしまう
Inputmask('(999) 999-9999').mask(tel); 問題
番号を貼り付けたり、自動入力したり、自分の書き方で入力したりすると、伝えた番号とは別の番号になり、スクリーンリーダーの利用者には空いた枠の並びが欄の値として読み上げられる
ネットショップの購入手続きで、荷物を発送したときにSMSで知らせるため、電話番号を入力します。欄の中には (__) - と形式が描かれていて、何を入力すればよいかが一目で分かり、入力すると数字が空いた枠を埋めていきます。開発者は、よく使われる入力マスクのライブラリーを1行で組み込むか、数字が入るたびに括弧とハイフンを足す数行のコードを自分で書いて、この欄を作ります。
利用者が、連絡先に「+1 212 555 0147」と保存してある自分の番号をコピーして貼り付けます。欄には「(121) 255-5014」と表示されます。電話番号らしく見えるので「次へ」を押すと、お知らせは別の人に届きます。マスクには10個の枠しかなく、最初に来た10桁の数字で順に埋めるためです。国番号の1は市外局番の最初の数字になり、最後の7は消えます。先に「+1」と入力しても同じで、+は何の知らせもなく捨てられ、1が最初の枠に入ります。2026年10月に、Chromiumで、Inputmask 5.0、IMask 7.6、Maska 3.2と、下の手書きのコードで試したところ、どれも貼り付けた番号を「(121) 255-5014」にしました。IMaskのイシュートラッカーにも、+7のマスクで、先頭に8を付けて貼り付けた番号がおかしくなるという同じ種類の報告があります。
作り方の違いによって、ほかにも次のように問題が出ます。
- ライブラリーの場合は、欄にフォーカスが移るとすぐに、パターンが欄の値になります。スクリーンリーダーは括弧と空いた枠を欄の中身として読み上げます。Inputmaskの利用者からは、「underline underline underline…」と読み上げられるという報告があります。
- 手書きのコードの場合は、変更のたびに値を組み立て直すため、カーソルが末尾へ飛びます。4桁目の間違いに気づいて消し、正しい数字を入力すると、その数字は最後に付きます。「(212) 550-1479」になってしまいます。
ここで満たしていない達成基準はなく、このガイドで扱うのはベストプラクティスです。達成基準3.3.2「ラベル又は説明」は、入力が必要な場所にラベルや説明を求めており、解説書(Understanding)は、入力する形式を示してもよいとしています(達成方法G89、形式と例を示す)。2つの修正前は、どちらもこれを満たします。欄にはラベルがあり、ライブラリーのパターンは形式まで示しています。番号を複数の書き方で受け付けることは、WCAGのどこにも求められていません。
このガイドの助言の根拠は、デザインシステムや利用者テストで得られた知見です。GOV.UKの電話番号のパターンは、入力マスクを避けるよう勧めています。利用者が好きな書き方で番号を入力しにくくなり、ほかの場所から番号を写して確かめにくくなるためです。そして、スペース、ハイフン、ダッシュ、括弧を受け付け、国番号と市外局番にも対応するよう求めています。Filament Groupは、空いた枠はフォーカスしたときに読み上げられても「意味のない雑音」にしかならず、入力中にスクリプトが値を書き換えると、スクリーンリーダーが値の切れ端を読み上げることがあると述べています。
問題は、マスクが受け取った文字をどう扱うかにあります。マスクは決まった枠の数を持つ1つの形式しか知らず、文字を順に読み、+やスペースのように形式に合わない文字は捨て、数字を次の枠に入れて、枠がなくなったところで止まります。別の書き方の番号は収まらず、何を捨てたかは利用者に伝わりません。カーソルが飛ぶのはブラウザーの動作です。スクリプトが入力欄の値を設定すると、HTMLの仕様によってカーソルはテキストの末尾に移るため、変更のたびに値を組み立て直すハンドラーは、カーソルを元の位置から動かしてしまいます。
1か所だけ、達成基準に近い部分があります。達成基準3.3.1「エラーの特定」は、ページが検出した入力エラーをテキストで説明することを求めており、解説書は、値が大きすぎたり小さすぎたりして、ページのコードが許される範囲に自動で変える場合も、そのエラーは説明しなければならないとしています。+と数字1つを黙って捨てるマスクは、これに近い状態です。下の修正はどちらも何も捨てないため、この問題は起きません。
マスクの形式どおりに1桁ずつ番号を入力する人以外は、誰でもこの問題に出会います。番号を貼り付ける人、ブラウザーに自動入力させる人、カードに印刷されたとおりに書く人です。連絡先アプリに保存した番号や、ブラウザーが自動入力する番号には、先頭に国番号が付いていることがあるため、貼り付けた番号が合わないのは、まれなことではありません。
10グループ中4グループに影響
- 全盲 (影響あり)
- 弱視 (影響あり)
- 色覚 (影響なし)
- ろう (影響なし)
- 難聴 (影響なし)
- 発話 (影響なし)
- 手の操作 (影響あり)
- 筋力・可動域 (影響なし)
- 認知 (影響あり)
- 光過敏 (影響なし)
- 視覚を使わない 欄にフォーカスがあり何も入力していないとき、値は(__) - というパターンなので、スクリーンリーダーは括弧と空いた枠を欄の中身として読み上げます。数字を入れていくと、数字と空いた枠が混ざって読み返され、貼り付けた番号が別の番号に変わっても、そのことは読み上げられません。
- 手の操作が限られる スイッチやマウススティック、指1本で入力する人は、キーを押す回数を減らすために番号をコピーしたり、ブラウザーに自動入力させたりします。マスクは先頭に+1の付いた番号を別の番号に変えてしまい、カーソルが末尾へ飛ぶ欄で直すには、さらに何度もキーを押すことになります。
- 言語・認知・学習の能力が限られる コピー元の番号と見比べて確かめるのは、欄が別の形で表示していると難しく、数字まで変わっているとさらに難しくなります。(121) 255-5014も電話番号らしく見えるため、間違っていると気づくきっかけがありません。
- 視覚が限られる 拡大表示では、欄の一部しか見えないことがあります。数字を直したあとにカーソルが末尾へ飛ぶと、次の数字は、見ていた数字から離れた末尾に入ります。
欄にはラベルがあり、ページはaxeのチェックを通り、スキャンは何も貼り付けません。EaseWebの診断は、電話番号の欄には+1 212 555 0147を、カード番号の欄には4242 4242 4242 4242を、スクリプトで貼り付け、フォームは送信せずに値を元に戻します。数字が変わってしまった欄と、値が空いた枠のパターンになっている欄を、人が試す項目として挙げます。達成基準の不適合ではないため、問題としては報告しません。カーソルがどこへ行くか、数字を入れるたびにスクリーンリーダーが何を読み上げるかは、人が確かめる必要があります。コーディングアシスタントに「(999) 999-9999の形式に整形する電話番号欄」を頼むと、どちらの修正前のコードも返ってくることがあります。
試してみる
連絡先カードの番号をコピーして電話番号欄に貼り付け、「次へ」を押してみましょう
問題1: まずTabキーで欄に移動し、フォームの下に表示される読み上げを確かめてください。次に番号を貼り付けます。どの数字が入りましたか?
問題2: 番号を貼り付けたあと、欄を空にして自分で2125550147と入力し、最初の5の直後をクリックして、Backspaceで消して別の数字を入力してください。カーソルはどこへ行きますか?
修正を適用します。 番号を貼り付けるか、スペース、ドット、括弧を入れて好きな書き方で入力し、「次へ」を押してください。
問題あり 修正できますか?
スクリーンリーダーの読み上げ:
(Tabで欄へ移動)
修正方法
番号は入力されたまま受け取り、数字だけを確かめる
欄の中にパターンを入れるマスクのライブラリー
<form> <label for="tel">電話番号</label> <input id="tel" name="tel" type="tel" autocomplete="tel"> <button type="submit">次へ</button></form>問題点3点
- 欄にフォーカスが移ると、値が (__) - というパターンになり、スクリーンリーダーはそれを欄の中身として読み上げる。
- マスクには10個の枠しかない。+1 212 555 0147を貼り付けると、最初の10桁で枠が埋まって「(121) 255-5014」と表示され、最後の7は消える。
- +は捨てられ、番号が変わったことは何も伝えられない。
マスクを使わず、送信するときに数字を確かめる
<form> <label for="tel">電話番号</label> <p id="tel-hint">市外局番を含めて入力してください。例:(212) 555-0147</p> <input id="tel" name="tel" type="tel" autocomplete="tel" aria-describedby="tel-hint tel-error"> <p id="tel-error"></p> <button type="submit">次へ</button></form>修正の手順5ステップ
- マスクを外し、スペース、括弧、ハイフン、ドットが入っていても、入力された番号も貼り付けられた番号も、そのまま欄に残す。
- ラベルの下に例を示し、
aria-describedbyで欄に関連付ける。例は欄と一緒に読み上げられ、入力中も画面に残る。 - 送信するときに数字だけを取り出し、11桁なら先頭の1を取り除く。「+1 212 555 0147」も「(212) 555-0147」も「212.555.0147」も、同じ10桁になる。
- 桁数が合わない値には、何を入力すればよいかを伝えるメッセージを、欄に関連付けて出す。
- 10桁の数字を送信する。リクエストはこのスクリプトを通らずに届くこともあるため、サーバーでも同じように数字を取り出す。
2つの修正前をどちらも直します。入力中に欄を書き換えるものはないので、カーソルは利用者が置いた場所から動かず、貼り付けた番号も欠けずに入ります。3.3.2は修正前と同じく満たし、形式は言葉で示されるようになります。
この方法を選ぶ理由:入力をはじかず、こちらで変換する
どちらも、番号をどう入力しても、どう貼り付けても受け付けます。使うべきなのは、マスクを使わない方法です。確かめる処理は同じでコードが少なく、番号は利用者が書いたとおりに表示されます。GOV.UK Notifyのチームは、書き直された番号を見せられて戸惑う利用者がいたと報告しています。欄を離れたときに区切る方法は、カード番号を4桁ずつ区切るように、どの番号も同じ形で見せたいデザインのためのものです。欄を変えるのは入力を終えたあとの1回だけで、カーソルを動かすことはありません。
マスクのライブラリーを残すしかない場合、パターンの表示を止めれば、空いた枠は値から消えます(Inputmaskでは showMaskOnFocus: false と showMaskOnHover: false、IMaskでは既定の lazy: true)。ただし、これは修正にはなりません。私たちのテストでは、パターンを表示しないIMaskでも、貼り付けた+1 212 555 0147は「(121) 255-5014」になりました。
maxlength は付けません。「(212) 555-0147」に合わせた14のように、形式に合わせた値を付けると、貼り付けた+1 212 555 0147が同じように途中で切れます。GOV.UKのテキスト入力のガイダンスも、厳しい文字数の制限は、利用者がいつもの書き方で値を入力するのを妨げると警告しています。桁数は、送信するときに数字の数で確かめます。
type="tel" と autocomplete="tel" は残します。前者はタッチ画面で電話番号用のキーパッドを出し、どんな文字も受け付けます。後者はブラウザーに番号を自動入力させます。自動入力される番号には国番号が付いていることもあり、上の確認はそれも想定しています。type="number" は数量のための型で、スペースや括弧を受け付けないため、電話番号には使いません。
カード番号も同じです。スペースがあってもなくても受け付け、autocomplete="cc-number" と inputmode="numeric" を付けます。カードに印刷されたとおりの形で見せたいデザインなら、欄を離れたときに4桁ずつ区切ります。「入力をはじかず、こちらで変換する」を参照してください。MM/DD/YYYYのような日付のマスクも同じ問題です。入力された日付の受け取り方は「入力もキーボード操作もできない日付ピッカー」で扱っています。
複数の国の番号を受け付けるショップでは、+と国番号を残す必要があり、各国の番号の決まりを知っているlibphonenumberのようなライブラリーを、キーを押すたびではなく、送信するときに使います。
修正の確認
6項目、マウス不要
確認方法: キーボード、タッチ、自動入力、スクリーンリーダー
OS、ブラウザー、支援技術のバージョン、ビルド、日付、各手順の実際の結果を記録してください。共通の電話番号欄やその整形の処理を変えたら、もう一度確認します。
制限
これは出発点となる実装例で、すべてのアプリケーションでの動作を保証するものではありません。例は、10桁で、国番号1が付くこともある米国の番号です。ほかの国では桁数が異なり、国をまたぐフォームでは+を残します。番号を区切りごとに3つの欄に分けて尋ねるのは別の問題で、「分割した欄それぞれに名前がない日付や電話番号の入力欄」で扱っています。日本語入力で全角の数字が入る欄の問題は、「全角数字を受け付けず、理由も示さない入力欄」で扱っています。送信に失敗したあとのメッセージの伝え方は、「直し方がわからないフォームエラー」で扱っています。
よくある問題を再現した学習用のサンプルです。実在のクライアントの診断結果ではありません。コードは出発点となる実装例のため、実際の製品でも確認してください。ここでは支援技術でのテスト結果は報告していません。
参考資料
- WCAG Understanding: labels-or-instructions(新しいタブで開きます)
- WCAG Technique G89(新しいタブで開きます)
- WCAG Understanding: error-identification(新しいタブで開きます)
- design-system.service.gov.uk: telephone-numbers(新しいタブで開きます)
- filamentgroup.com: politespace(新しいタブで開きます)
- github.com: 981(新しいタブで開きます)
- github.com: 800(新しいタブで開きます)
- github.com: 193(新しいタブで開きます)
EaseWebのサービス
修正した問題を、次のリリースで再発させない
このガイドのような修正方法を、コーディングエージェントが従うルールと、CIのチェックに組み込みます。あわせて定期的に、キーボードとスクリーンリーダーで手動の再テストを行います。