トピックを検索
分割した欄それぞれに名前がない日付や電話番号の入力欄
生年月日を3つのドロップダウンで尋ねるとき、ラベルが最初の欄にしか結び付いていないと、スクリーンリーダーは月と日の欄を名前なしで読み上げてしまう
<label for="dob-year"> 問題
スクリーンリーダーの利用者には月と日の欄が名前のないドロップダウンとして聞こえ、3つとも数字が入ると、どれが月の欄かを示すものが画面からなくなる
オンラインショップの会員登録フォームで、生年月日を尋ねています。「生年月日」というラベルの下に、年・月・日の3つのドロップダウンが斜線をはさんで1行に並びます。どのドロップダウンも、値を選ぶまでは「年」「月」「日」という最初の選択肢を表示しています。1990、05、12を選ぶと、行は「1990 / 05 / 12」になります。最初の選択肢の文字は消え、どれが月の欄でどれが日の欄かを示すものは画面に残りません。年・月・日の順に慣れていれば読めますが、月と日の順は国によって違い、画面にはどちらかを決めるものがありません。スクリーンリーダーでTabキーを押すと、「生年月日、コンボボックス、1990」、次に「コンボボックス、05」、「コンボボックス、12」と聞こえます。2つ目と3つ目の欄には名前がなく、スクリーンリーダーが読む名前も、音声操作で呼ぶ名前もありません。
ラベルはfor="dob-year"を指定したlabel要素なので、名前が付くのは最初のドロップダウンだけです。labelが名前を付けられるのは1つの欄だけで、3つの欄には付けられません。月と日のドロップダウンにはアクセシブル名がありません。最初の選択肢の「月」はselectの値で、名前ではないため、別の値を選ぶまでしか読まれません。これは、すべてのコントロールに名前を求める4.1.2を満たしません。分割した入力欄の2つ目以降に名前がないこの状態は、W3Cの失敗例F86にそのまま挙がっています。
1.3.1も満たしません。画面では3つの欄が1つの答えであることは明らかで、並び順と斜線がそれぞれの部分を示しています。しかし、その関係はコードのどこにも書かれていません。3つをまとめるグループがないため「生年月日」という言葉は2つ目と3つ目に届かず、この欄が月だと示すものは位置しかありません。
3.3.2も満たしません。3.3.2は、入力するあいだに使えるラベルか説明を求めています。「月」と示すのは最初の選択肢だけで、月を選んだとたんに消えます。文字を入力するとプレースホルダーが消えるのと同じです。そこから先は、全体にはラベルがあっても各欄にはなく、05と12を見分ける手がかりは並び順だけになります。W3Cの3.3.2の解説書も、3つの欄に分けた電話番号を例に、区切りの記号だけでは欄のラベルにならず、「電話番号」という1つのラベルでは3つの欄すべてには名前を付けられないと述べています。
問題が表に出るのは、フォームを埋め終えて見直すときです。日付を直しに戻った人や、送信前にフォームを確認する人は、3つの数字を前に、どの順で選んだかを思い出すか、推測するしかありません。
10グループ中3グループに影響
- 全盲 (影響あり)
- 弱視 (影響なし)
- 色覚 (影響なし)
- ろう (影響なし)
- 難聴 (影響なし)
- 発話 (影響なし)
- 手の操作 (影響あり)
- 筋力・可動域 (影響なし)
- 認知 (影響あり)
- 光過敏 (影響なし)
- 視覚を使わない スクリーンリーダーや点字ディスプレイの利用者には、最初のドロップダウンは「生年月日」と聞こえても、残りの2つは数字の入った名前のないコンボボックスとしか伝わらず、今どの欄にいるのかも、選んだ値が正しいかも確かめられません。
- 言語・認知・学習の能力が限られる すべての欄に数字が入ると、どれが月でどれが日かを示すものが画面からなくなります。日付を読み取るのが苦手な人や、見直しに戻ってきた人は、並び順から推し量るしかありません。
- 手の操作が限られる 音声操作の利用者は「生年月日をクリック」と話せば最初のドロップダウンには届きますが、残りの2つには話す名前がないため、番号を表示させて選ぶことになります。
axeのselect-nameルールとANDIは、名前のない2つのドロップダウンを見つけます。電話番号をテキストボックスに分けた場合も、axeのlabelルールが同じ誤りを見つけます。しかし、全体のラベルが各欄に届いているかは分かりません。各ドロップダウンにaria-labelを付ければ、「生年月日」と結び付いていなくても、名前がスクリーンリーダーにしか聞こえなくても、スキャナーは何も報告しなくなります。手早く直そうとして、かえって悪くなることもあります。3つのドロップダウンすべてにaria-label="生年月日"を付けてもスキャナーは何も報告しなくなりますが、スクリーンリーダーは「生年月日」を3回読み、どれが月の欄かはやはり分かりません。EaseWebの診断は、名前のある欄がグループに入っていないまとまりや、名前がスクリーンリーダーにしか届かないまとまりを、人が確認する項目(ew:split-field-manual-check)として挙げます。耳でも目でも各欄を見分けられるかは、人が確かめるしかないためです。
試してみる
Tabキーで生年月日の欄を順に移動し、それぞれの欄が何と読まれるか聞いてみましょう
日付は選択済みです。フォームの下で、各欄が名前付きで読まれるかを確かめてから、行を見てください。どれが月の欄でしょうか。
問題あり 修正できますか?
スクリーンリーダーの読み上げ:
(Tabで生年月日へ移動)
修正方法
すべての欄に名前を付け、全体のラベルを全部の欄に結び付ける
<label for="dob-year" class="field-label">生年月日</label><div class="date-parts"> <select id="dob-year" name="dob-year"> <option value="">年</option> <option>2026</option> … </select> / <select name="dob-month"> <option value="">月</option> <option>01</option> … </select> / <select name="dob-day"> <option value="">日</option> <option>01</option> … </select></div>問題点3点
最初のドロップダウンには「生年月日」という名前があります。問題はそれ以外です。
- 月と日のドロップダウンには名前がなく、スクリーンリーダーは「コンボボックス」と値しか読みません。
- 3つをまとめるものがないため、月や日の欄で「生年月日」は読まれません。
- 「年」「月」「日」の文字は最初の選択肢にしかなく、値を選ぶと消えます。
Fieldsetと欄ごとのラベル
<fieldset class="date-parts"> <legend class="field-label">生年月日</legend> <div class="date-part"> <label for="dob-year">年</label> <select id="dob-year" name="dob-year"> <option value="">年</option> <option>2026</option> … </select> </div> <div class="date-part"> <label for="dob-month">月</label> <select id="dob-month" name="dob-month"> <option value="">月</option> <option>01</option> … </select> </div> <div class="date-part"> <label for="dob-day">日</label> <select id="dob-day" name="dob-day"> <option value="">日</option> <option>01</option> … </select> </div></fieldset>修正の手順4ステップ
- 行を
fieldsetにし、3つのドロップダウンを1つのグループにします。 - 「生年月日」をその
legend、つまりグループの名前にします。フォーカスがグループに入ると、スクリーンリーダーは「生年月日、グループ、年、コンボボックス、1990」のように読みます。 - 各ドロップダウンに
idと、見えるlabel(年、月、日)をそれぞれ付けます。値を選んだ後も画面に残り、音声操作で「月をクリック」と話せるようになります。 - 斜線は外します。斜線が示していたことは、ラベルが言葉で示します。
これで修正前の例は直り、1.3.1、3.3.2、4.1.2を満たします。英国政府のGOV.UKの日付入力(Date input)や、米国政府のUS Web Design SystemのMemorable dateと同じ、各欄の上にラベルを置く形です。
この方法を選ぶ理由:まずHTMLの要素を使う
どちらもすべての欄に名前を付け、「生年月日」を3つの欄すべてに結び付けます。fieldsetと欄ごとのラベルを使ってください。フォームを埋めた後も、目で見る人にどれがどの欄かを伝えられるのはこちらだけで、しかも素のHTMLだけで済み、隠れた言葉もありません。隠した名前は、今回のリリースではデザインを変えられない場合の一時しのぎです。
並び順はラベルの代わりになりません。 年・月・日の順は日本の書き方で、多くの国では日・月・年、米国では月・日・年です。欄ごとにラベルがあれば、どの順でも伝わります。ラベルがなければ、順番は推測です。利用者が慣れた順に並べ、そのうえでラベルも付けます。
最初の選択肢は名前ではありません。 「年」や「選択してください」のような案内は、空の最初の選択肢として残して構いませんが、それはselectの値で、別の値を選ぶまでしか読まれません。フレームワークもこの形で案内を入れます。DjangoのSelectDateWidgetは、必須でない日付のとき、empty_labelでこの案内を受け取ります。名前はラベルから付けます。
フレームワークの補助機能は、各欄に名前を付けません。 Railsのdate_selectは、idが_1i、_2i、_3iで終わる3つのselectを出力するため、属性に対して書いたラベルはどれにも結び付きません。Djangoの標準のas_div()レイアウトでは、SelectDateWidgetの3つのselectがfieldsetに入り、フィールドのラベルがlegendになりますが、各selectにはラベルが付きません。as_p()、as_table()、as_ul()のレイアウトでは、ラベルは最初のselectにしか結び付きません。どちらでも、各欄のラベルは自分で付けるか、自前のコンポーネントで欄を描画します。
電話番号と郵便番号は、1つの欄のほうが向いています。 市外局番・市内局番・加入者番号に分けた電話番号や、3桁と4桁に分けた郵便番号も、日付と同じく欄ごとに名前が必要です。ただ、よりよい直し方は分けないことです。1つの欄なら、どう入力しても貼り付けても番号を受け取れます。米国政府のUS Web Design Systemは電話番号を複数の欄に分けないよう求め、GOV.UKは利用者が慣れた書き方のまま入力できるよう求めています。入力に合わせて書式を整える欄には別の問題があり、入力した番号や貼り付けた番号が変わってしまう入力マスクで扱います。2つのドロップダウンに分けたカードの有効期限には、legendを「有効期限」にしたfieldsetの中で、「月」と「年」のラベルを付けます。
ブラウザーに入力させます。 生年月日なら、3つの欄にautocomplete="bday-year"、"bday-month"、"bday-day"を付けると、ブラウザーが保存している値を入力できます。これは別の達成基準で、自動入力が効かないフォームの入力欄で扱います。
フォーカスは動かしません。 1つの欄を埋めたとたんに次の欄へフォーカスを移さないでください。GOV.UKの日付入力のパターンも、欄の間を自動で移動させないよう求めています。値を直しに戻る人を驚かせるためです。自動でフォーカスが進む欄の問題は、キーボードで打ち間違いを直せないワンタイムコードの入力欄で扱います。
エラーは欄を示します。 1つの欄が誤っていたら、メッセージでどの欄かを伝え(「月は1から12で入力してください」)、その欄に印を付けます。直し方がわからないフォームエラーを参照してください。カレンダーから選ぶ日付は別のコントロールで、入力もキーボード操作もできない日付ピッカーで扱います。
デザインの案
欄を分けても、どの欄にも言葉を残す
同じ生年月日を3通りに描きました。月と日は入力済みで、年は空です。それぞれをTabで移動して年を入力してみてください。2つはどの欄にも名前が残り、1つは入力するにつれて名前が消えます。
デザインファイルで
- すべての欄を埋めた状態も描き、どの欄にも名前が見えるか確かめる。
- 質問は欄の上に一度だけ、まとまりの見出しとして書く。
- 欄は利用者が書き慣れた日付の順に並べ、順番にかかわらず名前を付ける。
- 各欄のフォーカスの枠と、誤った1つの欄だけのエラー表示を描く。
- ラベルの色の横にコントラスト比を書く。4.5:1以上が必要(1つ目の例では9.46:1)。
合格
- 枠線の切れ目に置いたラベル 3つの枠付きの欄の、上の枠線の切れ目に名前を置きます。白地に13pxの#4a4541で9.46:1です。空でも入力後も名前はそこにあり、ラベルが動く必要はありません。1pxの#8f8882の枠線は3.49:1です。
- 1つの枠を区切り、各区画に名前 3つの欄を、細い線で区切った淡い#f6f4f2の1つの枠として描き、各区画の上部に小さな名前(13pxの#4a4541、8.63:1)、その下に値を置きます。1つの答えに見えながら、どの部分にも名前があります。フォーカスの枠は区画ごとに付きます。
不合格
- 同じ枠に「YYYY」「MM」「DD」だけWCAG 3.3.2 同じ枠の各区画に、灰色の「YYYY」「MM」「DD」(#5c5650、6.60:1)を置くだけで、名前はありません。数字を入力すると文字は消え、埋まった区画には05と12が並ぶだけで、どちらが月かを示すものが残りません。
修正の確認
4項目、マウス不要
確認方法: キーボード、スクリーンリーダー、拡大表示
OS、ブラウザーと支援技術のバージョン、ビルド、実施日、各手順の実際の結果を記録してください。共通の日付コンポーネントを変更した際は、再度確認します。
制限
このサンプルは、どのアプリケーションでも同じ結果になることを保証するものではありません。スクリーンリーダーはフォーカスがグループに入ったときにグループの名前を読むため、下からShift + Tabキーで戻ると、年の欄ではなく日の欄で読まれます。スクリーンリーダーによっては、欄ごとに繰り返し読むこともあります。このガイドが扱うのは、いくつかの部分に分けて尋ねる日付です。ワンタイムコードのように1文字ずつ欄を分けた値は、貼り付けられないワンタイムコードの入力欄で扱います。1つの設問の下に並ぶラジオボタンやチェックボックスは、設問名がないラジオボタンとチェックボックスのグループで扱います。実際に使用する支援技術で、フォーム全体を確認してください。
よくある問題を再現した学習用のサンプルです。実在のクライアントの診断結果ではありません。コードは出発点となる実装例のため、実際の製品でも確認してください。ここでは支援技術でのテスト結果は報告していません。
参考資料
- WCAG Understanding: info-and-relationships(新しいタブで開きます)
- WCAG Understanding: labels-or-instructions(新しいタブで開きます)
- WCAG Understanding: name-role-value(新しいタブで開きます)
- WCAG Technique F86(新しいタブで開きます)
- WCAG Technique ARIA17(新しいタブで開きます)
- design-system.service.gov.uk: date-input(新しいタブで開きます)
- designsystem.digital.gov: memorable-date(新しいタブで開きます)
EaseWebのサービス
修正した問題を、次のリリースで再発させない
このガイドのような修正方法を、コーディングエージェントが従うルールと、CIのチェックに組み込みます。あわせて定期的に、キーボードとスクリーンリーダーで手動の再テストを行います。