本文へスキップ
サイト総合診断

フォームのラベル(label)を正しく関連づける

ラベルは、入力欄が「何を入れる欄か」を示すテキストです。見える人にはフォームの見た目で分かりますが、その対応づけを HTML でも明示しないと、スクリーンリーダー利用者は「編集テキスト」としか分かりません。label と入力欄を for/id で結ぶか、label で囲むだけで解決します。placeholder はラベルの代わりにはなりません。

執筆: 公開:

フォームのラベルはなぜ必要ですか?

ラベルが入力欄に結び付いていないと、スクリーンリーダーは「編集テキスト、空欄」としか読み上げず、何を入力する欄か分かりません。正しく関連づければ、欄にカーソルが入った瞬間に「メールアドレス、編集テキスト」と読み上げられます。さらにラベルのクリックで欄にフォーカスが移るため、チェックボックスなど小さな部品の操作も楽になります。

フォームは、見える人にとっては「欄の左(または上)にある文字=この欄の名前」と直感で結び付きます。 しかしこの対応づけは見た目の位置関係で成立しているだけで、HTML 上で明示しない限り、スクリーンリーダーには伝わりません。 結果、利用者は名前の分からない空欄を次々に読まされることになります。

副次的な利点として、ラベルを正しく結ぶとラベルの文字をクリック(タップ)しても入力欄にフォーカスが入るようになります。 小さなチェックボックスやラジオボタンの当たり判定が広がり、操作性も上がります。

label と入力欄はどう関連づけますか?

label の for 属性に、入力欄の id と同じ値を書いて結び付けます。for="email" の label と id="email" の input が一組になります。この id はページ内で一意にする必要があり、重複すると関連づけが壊れます。もう一つの方法として、label で input ごと囲む書き方もあり、こちらは id を使わずに済みます。

for / id による明示の関連づけ
<!-- 明示の関連づけ: for と id を一致させる(id はページ内で一意) -->
<label for="email">メールアドレス</label>
<input type="email" id="email" name="email" autocomplete="email">

label で入力欄を囲む方法との違いは何ですか?

label で input を囲む「暗黙の関連づけ」は、id を振らずに済むぶん簡潔で、id の重複事故も起きません。一方 for/id による「明示の関連づけ」は、ラベルと入力欄が DOM 上で離れていてもよいため、複雑なレイアウトに向きます。どちらでも支援技術には正しく伝わるので、書きやすい方を選んで構いません。

label で囲む暗黙の関連づけ
<!-- 暗黙の関連づけ: label で囲む(id 不要) -->
<label>
  メールアドレス
  <input type="email" name="email" autocomplete="email">
</label>

<!-- チェックボックスは特に、囲むとラベルクリックで ON/OFF できて楽 -->
<label>
  <input type="checkbox" name="agree">
  利用規約に同意する
</label>
2 つの関連づけ方法の比較
方法id の要否向いている場面
for / id(明示)必要(一意に)ラベルと欄が離れる複雑なレイアウト
label で囲む(暗黙)不要シンプルな一組。id 重複事故を避けたいとき

ラベルを画面に表示したくないときはどうしますか?

検索ボックスのように見た目上ラベルを省きたい場合は、aria-label で入力欄に直接名前を付けます。aria-label="サイト内を検索" と書けば、画面には出ませんがスクリーンリーダーには読み上げられます。見た目のラベルを消すために display:none にすると読み上げからも消えるので、視覚的に隠すなら sr-only(クリップ)を使うか aria-label にします。

表示しないラベル: aria-label / sr-only
<!-- ラベルを見せたくない検索欄: aria-label で名前を付ける -->
<input type="search" aria-label="サイト内を検索" placeholder="キーワード">

<!-- あるいは視覚的にだけ隠す(読み上げには残る)。display:none にはしない -->
<label for="q" class="sr-only">サイト内を検索</label>
<input type="search" id="q" placeholder="キーワード">

placeholder をラベルの代わりにしてはいけないのはなぜですか?

placeholder は入力すると消えるため、入力中に「何の欄だったか」を確認できなくなります。色も薄く、コントラスト不足で読みにくい問題もあります。支援技術によっては placeholder をラベルとして扱わないものもあります。placeholder は入力例(山田太郎 など)の補助に留め、欄の名前は必ず label で別に示してください。

「ラベルを消して placeholder だけにする」デザインはよく見かけますが、実用上いくつも問題を抱えています。

  • 入力すると消える — 入力途中で「何の欄だっけ」を確認できない
  • コントラストが低い — 既定の placeholder は薄く、読みにくい人がいる
  • 支援技術が名前として扱わないことがある — ブラウザ・環境依存で、あてにできない

placeholder は「090-1234-5678」のような入力例の補助に留め、欄の名前は必ず label で示します。両立させれば、名前も例も伝わります。

必須やエラーはどう伝えればいいですか?

必須は required 属性を付け、視覚的な「※」だけに頼らないようにします。エラーメッセージは、該当の入力欄に aria-describedby で結び付けると、フォーカス時に読み上げられます。色を赤くするだけでは、色の区別がつきにくい利用者に伝わりません。テキストと属性の両方で状態を伝えるのが原則です。

必須・エラーの伝え方
<!-- 必須とエラーを、色だけでなくテキスト・属性で伝える -->
<label for="tel">電話番号</label>
<input
  type="tel"
  id="tel"
  required
  aria-describedby="tel-error"
  autocomplete="tel"
>
<p id="tel-error">ハイフンを除いた半角数字で入力してください。</p>

aria-describedby でエラー文を欄に結び付けると、フォーカス時に「電話番号、編集テキスト、ハイフンを除いた…」と名前とエラーが続けて読み上げられます。 エラーを赤字にするだけでは、色の判別が難しい人に届きません。色・テキスト・属性の三重で伝えるのが安全です。

ラベルが正しく付いているか、どう確認しますか?

各入力欄をクリックしてみて、ラベル文字をクリックしたときに欄へフォーカスが移れば関連づけは成功しています。移らなければ for/id がずれています。スクリーンリーダーで Tab 移動し、各欄で名前が読み上げられるかも確認します。本ツールのアクセシビリティ診断は、名前(label・aria-label)の無い入力欄を検出します。

最も簡単な確認は「ラベルの文字をクリックして、対応する欄にカーソルが入るか」です。入れば関連づけは生きています。 自動チェックは「名前の有無」までは判定できますが、名前が内容と合っているかは人の確認が要ります。 画像側の代替テキストは alt 属性の正しい書き方 を参照してください。

参考にした一次情報

関連する解説

自分のサイトは、実際どうなっているか

この記事で説明した項目は、すべて無料の診断ツールで実測できます。URL を入れるだけ・登録不要です。

無料で診断する