やく半数のウェブサイトのホームページには、フォーム入力ラベルが欠けています。これは、ウェブ上で最も一般的でありながら、最も修正しやすいアクセシビリティ上の不具合の1つです。このガイドでは、ウェブサイトの所有者、開発者、コンプライアンス担当者に向けて、フォームをすべての人にとって使えるものにするために必要な具体的な手法を解説します。適切なラベリング、意味のあるエラーメッセージ、そしてインクルーシブなバリデーションパターンについて取り上げます。
WebAIMによると、48.6%のウェブサイトのホームページでフォーム入力ラベルが欠落している — つまり、ラベルのない入力欄は、ウェブ全体で最も一般的なアクセシビリティ上の不具合の1つになっているということです。これが実際に何を意味するか考えてみてください。スクリーンリーダー利用者があなたの問い合わせフォームに到達し、Tabキーでフィールドを移動していくと、何度も何度も「編集テキスト」としか読み上げられません。スクリーンリーダーはフォームフィールドのラベルを読み上げます — ラベルがなければ、ユーザーは文脈のない「編集テキスト」しか聞けず、何の情報を入力すべきか分かりません。 フォームは多くの場合、ウェブサイトの中で最もビジネス上重要な部分です — 購入フロー、サインアップ画面、お問い合わせページ、サポート依頼など — にもかかわらず、支援技術を使う人々にとっては、最も一貫して壊れた体験のまま放置されがちです。
フォームのアクセシビリティが思っている以上に重要な理由
米国の成人の4人に1人が障害とともに暮らしていることを考えると、アクセシブルなフォームバリデーションは「あると良いもの」ではなく「必須」です。 この中には、全盲やロービジョンの人、キーボード操作に頼る運動障害のある人、明確な指示を必要とする認知障害のある人、音声コントロールソフトでフォームに入力する人などが含まれます。ラベルのないフィールド、あいまいなエラーメッセージ、色だけに依存したバリデーションパターンの1つ1つが、あなたのオーディエンスのかなりの割合の目の前で、静かに扉を閉ざしてしまうのです。
多くの障害のあるユーザーは、情報を送信する際にエラーに遭遇しても、それをどう直せばよいかについて明確な指示が与えられません — その結果、試行を諦めてよりアクセシブルなフォームを探すか、誰か他の人の助けを借りるかの2択を迫られますが、どちらも理想的な体験とは言えません。 ビジネスの観点から見ると、アクセシブルなフォームはユーザー体験を向上させ、離脱率を下げ、法的要件を満たします。 コンプライアンスの観点からは、WCAG 1.3.1(情報及び関係性)と4.1.2(名前、役割、値)は、2008年にWCAG 2.0が公開されて以来存在するレベルAの要件です。 これらはレアケースでも高度なテクニックでもなく、標準における基礎的な期待事項です。
WebAIM Millionレポートによると、フォームラベルの欠如は、ウェブ全体で最も多いアクセシビリティエラーの1つとして一貫して上位に挙げられており、実装の失敗に関する調査からその理由が分かります。組織は複雑なソリューションに注目する一方で、障害のある人が実際にサービスを利用できるようにする基本的なパターンを無視しているのです。 良いニュースとしては、これらの問題のほとんどを修正するのに特別なことは必要なく、意図を持って正しいHTMLを書くことだけで済むという点です。
フォームに適用されるWCAG達成基準
実装に入る前に、フォームにどのWCAG達成基準が適用されるのかを把握しておくと役に立ちます。Web Content Accessibility Guidelines(WCAG)は、知覚可能(Perceivable)、操作可能(Operable)、理解可能(Understandable)、堅牢(Robust)(POUR)の4つの主要原則を定めており、これがインクルーシブなバリデーションシステムの背骨となります。 この枠組みの中で、いくつかの達成基準がフォームデザインに直接関係しています。
特に関連性の高い基準には、1.3.1 情報及び関係性(レベルA)があります。これは、提示によって伝えられる情報、構造、関係性がプログラムによって解釈可能であることを求めるものです。2.4.6 見出し及びラベル(レベルAA)は、見出しとラベルがトピックや目的を説明していることを求めます。3.3.2 ラベル又は説明(レベルA)は、コンテンツがユーザー入力を必要とする場合にラベルまたは説明を提供することを求めます。そして4.1.2 名前(Name)、役割(Role)、値(Value)(レベルA)は、すべてのユーザーインターフェイスコンポーネントについて、その名前と役割がプログラムによって解釈可能であることを求めます。
エラーの特定、指示、提案、防止を扱うWCAG 3.3.1〜3.3.4に従うことで、すべてのユーザーにとってより簡単で直感的なフォームを作ることができます。 これらは恣意的なハードルではなく、それぞれが実際のユーザーニーズを反映しています。各ルールの「なぜ」を理解することで、正しく実装しやすくなり、また、境界的なケースで妥当な判断を下しやすくなります。
ラベルを正しく扱うこと:アクセシブルなフォームの土台
ラベルは単なる視覚的なヒントではありません。ラベルはテキストによる説明とフォームコントロールをプログラム的に結びつけるものであり、支援技術がフィールドの用途を特定するための主要な仕組みです。この結びつきを作る最も堅牢な方法は、HTMLの<label>要素とそのfor属性を使い、対応するinputのidを指すようにすることです。
<!-- 間違い:プレースホルダーだけではアクセシブルなラベルにならない -->
<input type='email' placeholder='Email address'>
<!-- 正しい:for/idで関連付けられた明示的なラベル -->
<label for='email'>Email address</label>
<input type='email' id='email' name='email'>
ラベルは常に可視であるべきで、プレースホルダーだけにしてはいけません。プレースホルダーはユーザーが入力を始めると消えてしまい、文脈が失われます。 これは非常に重要な違いです。プレースホルダーテキストはラベルとして使うことを想定して設計されていません。ユーザーが入力を始めた瞬間に消えてしまい、色のコントラストが不十分なことも多く、多くのスクリーンリーダーはプレースホルダーをフィールドのアクセシブルネームとして確実に扱ってくれません。プレースホルダーだけに頼ることは、支援技術を使う人だけでなく、すべてのユーザーにとって不親切です。
関連するフィールドがグループになっている場合 — 例えば、一連のラジオボタンやチェックボックスのブロックなど — 正しいパターンは<fieldset>と<legend>を使うことです。チェックボックスやラジオボタンのような関連オプションは、fieldsetとlegendでグループ化することで、複雑なフォームを理解しやすくします。
<fieldset>
<legend>Preferred contact method</legend>
<input type='radio' id='contact-email' name='contact' value='email'>
<label for='contact-email'>Email</label>
<input type='radio' id='contact-phone' name='contact' value='phone'>
<label for='contact-phone'>Phone</label>
</fieldset>
見た目としてラベルが冗長になってしまう状況 — 例えば、明確に「Search」と書かれたボタンの横に単独で置かれた検索フィールドなど — では、aria-labelやaria-labelledbyを使って、可視テキストを表示せずにアクセシブルネームを提供することができます。ただし、これは控えめに使ってください。スクリーンリーダー利用者は、ラベルやフィールドセット、その他の構造要素と関連付けられていることで、フォームコントロールをより簡単に特定し理解できます — そして可視ラベルは、認知障害のある視覚ユーザー、400%までズームしているユーザー、長いフォームの中で一時的に自分の位置を見失った人など、すべての人にとって有益です。
また、必須フィールドは、required属性やaria-requiredを使って、視覚的にもプログラム的にも示さなければなりません。 赤いアスタリスクだけでは不十分です — フォームの冒頭に「*が付いているフィールドは必須です」のような短い注記を入れ、マークアップ内でrequired属性を設定して、ユーザーがそのフィールドにフォーカスしたときに支援技術が「必須」であることを読み上げられるようにしてください。
本当に役に立つエラーメッセージを書く
エラーメッセージは、多くのフォームが2つ目の形でユーザーを失望させるポイントです。ユーザーがフォームを送信してバリデーションエラーが発生した後、ユーザーは3つのことを知る必要があります。エラーが起きたこと、どのフィールドが原因なのか、そしてどう直せばよいのかです。多くのフォームエラーは、このうち最初の1つにしか答えておらず、その伝え方も不十分です。
「無効な入力」や「エラー」のようなあいまいなエラーメッセージは、何が問題だったのか、どう修正すればよいのかをユーザーに伝えません。すべてのエラーメッセージは、具体的な問題を特定し、具体的な解決策を示すべきです。
スクリーンリーダーとの互換性を確保するために、エラーメッセージはaria-invalid="true"やaria-describedbyといったARIA属性を使ってDOMに統合し、エラーメッセージを対応するフォームフィールドに直接関連付ける必要があります。 適切にマークアップされたエラー状態は次のようになります。
<label for='email'>Email address</label>
<input
type='email'
id='email'
name='email'
aria-invalid='true'
aria-describedby='email-error'
>
<span id='email-error' role='alert'>
Please enter a valid email address, for example: [email protected]
</span>
aria-invalid="true"属性は、そのフィールドの値が現在無効であることをスクリーンリーダーに伝えます。aria-describedby属性はエラーメッセージを含む要素を指し、ユーザーがその入力欄にフォーカスしたときにスクリーンリーダーがエラーメッセージを読み上げます。エラースパンに付けたrole="alert"は、その要素がDOMに挿入された際に、ユーザーがそこへ移動しなくても即座に読み上げられるようにします。
ミニマルなデザインでは、フィールドが無効であることを示すのに赤色だけを使いたくなるかもしれません — しかし、色だけに頼ることは、WCAG 1.4.1「色の使用」が示すように不十分です。人によって色の見え方は異なり、その赤色に気づかない人もいるからです。 解決策は、色付きのエラー状態に追加の視覚要素を組み合わせることです — アイコンを使うこともできますが、それだけではなぜフィールドが無効なのか理解できない場合もあるため、最もインクルーシブな解決策は、テキストメッセージを明示的に表示することです。
具体的なエラーメッセージは、認知面での困難があるユーザー、注意力が低下しているユーザー、スクリーンリーダーを使うユーザーにとって特に有用です — 不適切に書かれたフィードバックはフラストレーションを招き、フォームの放棄につながることさえあります。 エラーメッセージはユーザーの視点から書きましょう。何を入力する必要があり、今すぐどう修正できるのかを伝えるのです。
バリデーションのタイミングとフォーカス管理
いつバリデーションを行うかは、どのようにバリデーションを行うかと同じくらい重要です。早すぎるタイミング — 例えば、ユーザーがまだ入力中の段階でエラーを出すと — ユーザーの流れを中断し、時期尚早なクレームで邪魔してしまうリスクがあります。送信時だけにエラーを出すと、ユーザーは長いフォームをスクロールしながら、どのフィールドに注意が必要なのか探し回ることになるかもしれません。適切なのは、段階的なアプローチです。
重要なフィールドにはリアルタイムのフィードバックを組み合わせ、フォーマットが決まっている入力にはフォーカスが外れたタイミングでチェックを行い、送信時には包括的なエラーチェックを行いましょう。 実際には、パスワードやメールアドレスのような複雑なフォーマットは、ユーザーがそのフィールドから離れたとき(on blur)にバリデーションし、キー入力ごとに発火するインラインバリデーションでユーザーを邪魔しないようにします。そしてフォーム送信時には全体をチェックし、すべてのエラーを一度に明確に伝えます。
送信後は、最初のエラーに自動的にフォーカスを移動させ、ユーザーが効率的に修正できるようにします。 エラーが複数ある場合、最もアクセシブルなパターンは、フォームの先頭にエラーの一覧をまとめたサマリーを置き、そこにフォーカスを移動させることです。サマリー内の各エラーは、該当フィールドへジャンプするリンクにします。これにより、ユーザーは送信直後にエラーサマリーを聞き、何をどれだけ直す必要があるかを把握し、それぞれの問題箇所へ直接移動できます。
<!-- フォーム先頭に配置し、プログラム的にフォーカスを当てるエラーサマリー -->
<div id='error-summary' role='alert' tabindex='-1'>
<h2>2 errors found. Please correct the following:</h2>
<ul>
<li><a href='#email'>Email address: Please enter a valid email</a></li>
<li><a href='#phone'>Phone number: Please use the format (555) 555-5555</a></li>
</ul>
</div>
マウスなしでも論理的なタブ順と見やすいフォーカスインジケーターでフォームを操作できるようにしてください。 ブラウザのデフォルトのフォーカスリングは、法的にも機能的にも最低限の基準です — しかし多くのデザインチームはCSSでoutline: noneを指定してこれを消してしまい、代替を用意しません。これは、キーボードのみのユーザーにとってフォームを事実上使えないものにしてしまいます。明確でコントラストの高いフォーカスインジケーターは、WCAG 2.4.7(レベルAA)および、より厳格なWCAG 2.2の2.4.11で求められています。ブランドガイドラインがデフォルトのフォーカスリングと合わない場合は、削除するのではなく置き換えてください。
エラーが起きる前に指示とヒントを提供する
最良のフォームエラーは、そもそも表示される必要のないエラーです。適切に配置された指示やヒントは、そもそものエラー発生を防ぎ、すべてのユーザーにとってより良いものになります。必須入力や、特定のフォーマット・値・長さを必要とする入力には、その情報を要素のラベル内、またはプログラム的に関連付けられた説明の中で提供する必要があります。
フィールドラベルは、何を入力すべきかを示す最初の視覚的な指示であり、必要に応じて説明が続きます。視覚ユーザーが説明を見られるのと同じように、スクリーンリーダー利用者もその説明を認識できる必要があります — そのためには、aria-describedby属性を使って説明を入力欄に関連付けます。aria-describedbyは説明要素のidを受け取り、ユーザーがフィールドにフォーカスしたときにスクリーンリーダーが自動的に説明を読み上げるようにします。
<label for='phone'>Phone number</label>
<input
type='tel'
id='phone'
name='phone'
aria-describedby='phone-hint'
>
<span id='phone-hint'>Format: (555) 555-5555</span>
可能な限り、期待される入力を明確にするための例を示しましょう — 例えば、日付フィールドがMM/DD/YYYY形式を要求する場合、「12/25/2024のように入力してください」のような例を含めます。 パスワードフィールドについては、ユーザーが各ルールに違反するたびに1つずつ要件を明かすのではなく、最初から要件を明示しておきましょう。可能であれば、フォームには時間制限を設けず、ユーザーが自分のペースでフォームを完了できるようにすべきです — どうしても時間制限が必要な場合は、ユーザーがそれをオフにしたり延長したりできるオプションを用意してください。
autocomplete属性も、見落とされがちなアクセシビリティの仕組みです。autocomplete="email"、autocomplete="given-name"、autocomplete="street-address"のような値を設定すると、ブラウザやパスワードマネージャーがフィールドを正しく自動入力できるようになり、運動障害や認知障害のあるユーザー、あるいは繰り返しの入力を負担に感じるすべての人の負担を大幅に軽減します。WCAG 1.3.5(入力目的の特定、レベルAA)は、個人情報を収集するフィールドに対してこれを求めています。
フォームのアクセシビリティをテストする
ルールを知ることと、自分のフォームが実際にそれに従っているかを知ることは別問題です。最も信頼できるアプローチは、複数のテスト手法を組み合わせることです。LighthouseやWAVEのようなツールは、自動的に問題を検出するのに役立ちますが、キーボードのみの操作やスクリーンリーダーを使った手動テストは、実際の使い勝手の問題を見つけるために不可欠です。
キーボードテストでは、単にマウスを抜いてフォームの入力を試してみてください。Tab、Shift+Tab、矢印キー、Enter/Spaceだけで、すべてのフィールドに到達し、すべてのボタンを操作し、すべてのエラーメッセージを受け取れるはずです。どこかで行き詰まるようなら、それは不具合です。スクリーンリーダーテストでは、WindowsではNVDAとFirefox、macOSではVoiceOverとSafariを使います。スクリーンリーダーはそれぞれ少しずつ挙動が異なります — ショートカットも、意味づけの読み上げも、対応機能も違います。例えば、NVDAはFirefoxとの相性が良く、VoiceOverはSafariで最もよく動作します。 少なくとも2つの組み合わせでテストすることで、最も幅広い問題を検出できます。
WAVEやAxeのようなツールは、ラベルの欠落、不適切なARIA属性、コントラスト不足などをフォームからスキャンするのに適しています。 これらの自動ツールはCI/CDパイプラインに直接組み込むことができ、本番環境に到達する前にリグレッションを検出できます。ただし、アクセシビリティガイドラインはニュアンスが多いため、自動ツールが検出できるWCAGの問題は約30%に過ぎません — そのため、自動テスト層は手動レビューと、理想的には支援技術に依存する実ユーザーによるテストで補完する必要があります。
マークアップを手動でレビューする際には、各フォームフィールドについて次の質問を投げかけてください。可視ラベルはあるか? そのラベルはfor/idまたはARIAでプログラム的に関連付けられているか? ヒントテキストはaria-describedbyで関連付けられているか? すべてのエラー状態でaria-invalid="true"が設定され、エラーメッセージがaria-describedbyで参照されているか? 必須フィールドにrequired属性は付いているか? キーボードだけで、すべてのインタラクティブ要素に到達し操作できるか?
重要なポイント
- すべての入力欄にはプログラム的なラベルが必要です。 すべてのフォームフィールドに
<label for='...'>を使い、プレースホルダーテキストだけに頼ってはいけません。すべてのフォームフィールドにはプログラム的なラベルが必要であり、例外はありません — プレースホルダーテキストはラベルではありません。 - エラーメッセージは問題を特定し、解決策を示さなければなりません。 エラーメッセージは問題を特定し、どう直せばよいかを示す必要があり、
aria-describedbyを使ってフィールドと関連付けるべきです。 - 色だけに頼ってはいけません。 ステータス表示に色だけを使ってはいけません — テキストやアイコン、その他の非色覚的なインジケーターを色の手がかりと併用してください。
- 送信後のフォーカスを適切に管理する。 エラーは明確に特定され、問題のある要素への素早いアクセスが提供され、ユーザーが簡単にエラーを修正してフォームを再送信できるようにすべきです。 送信に失敗した後、フォーカスをエラーサマリーに移動することがゴールドスタンダードです。
- 思い込みではなく、実際のツールでテストする。 フォームのアクセシビリティを維持することは一度きりの作業ではなく、コンプライアンスとユーザビリティを保つために定期的なテストと更新が必要です。 自動スキャンに加え、重要なフォームを更新するたびに、キーボードのみの操作とスクリーンリーダーによるテストを組み合わせて実施してください。
