HTMLのlabelタグ入門:フォームを迷わず入力できる書き方と改善例
labelタグは、フォームの「メールアドレス」「お問い合わせ内容」といった説明を、対応する入力欄に結び付けるHTML要素です。
正しく結び付けると、説明文をクリックしただけで入力欄にフォーカスが移ります。チェックボックスやラジオボタンでは文字部分もクリックできるため、スマートフォンでも選びやすくなります。スクリーンリーダーにも入力欄の目的が伝わります。
この記事では、次の内容を実際に試せるコードで解説します。
labelと入力欄を結び付ける基本for・id・nameの役割の違い- チェックボックスやラジオボタンでの使い方
placeholderで代用できない理由- よくある失敗と確認方法
ここがポイント: 基本形は、
labelのforと入力欄のidに同じ値を指定する書き方です。見た目を隣に置くだけでは、HTML上の関連付けにはなりません。
labelタグの役割と前提環境
labelは、入力欄の目的を人とブラウザの両方に伝えるために使います。 見た目を整えるだけのタグではありません。
この記事のコードは、2026年7月時点のHTML Living Standardに沿った通常のHTMLです。Chrome、Edge、Firefox、Safariなどの現行ブラウザで動作し、JavaScriptや外部ライブラリは必要ありません。
labelを関連付けられる代表的な要素は次のとおりです。
input(type="hidden"を除く)textareaselectbuttonoutputprogressmeter
ただし、送信ボタンは通常、<button>送信する</button>のようにボタン自身の内容で目的を示します。何にでもlabelを追加するのではなく、入力欄や選択肢の説明が必要な場面で使うのが基本です。
labelがあると何が変わるのか
正しい関連付けには、主に二つの効果があります。
- ラベルをクリックまたはタップすると、対応する入力欄が選択される
- スクリーンリーダーが、入力欄とその名前を関連付けて読み上げられる
特に小さなチェックボックスを直接狙わず、「利用規約に同意する」という文字全体を押せる効果は実用的です。操作できる範囲が広がり、マウス操作が苦手な人やタッチ画面を使う人も選択しやすくなります。
基本はforとidを同じ値にする
最も分かりやすく互換性も高いのは、forとidを使う明示的な関連付けです。
<label for="user-email">メールアドレス</label>
<input
type="email"
id="user-email"
name="email"
autocomplete="email"
>
ここでは、次の二つが一致しています。
labelのfor="user-email"
inputのid="user-email"
ブラウザはこの一致を見て、「メールアドレス」というラベルがinputの説明だと判断します。ラベル部分をクリックして、入力欄にカーソルが移れば関連付けが機能しています。
for・id・nameは役割が違う
初心者が混同しやすいのが、idとnameです。どちらも入力欄に指定しますが、用途は異なります。
for: どのidを持つフォーム部品のラベルなのかを示すid: ページ内の要素を識別し、labelやCSS、JavaScriptなどから参照するname: フォーム送信時の項目名になる
たとえば、上の入力欄にtanaka@example.comを入力して送信すると、サーバー側では概念的に次の組み合わせを受け取ります。
email=tanaka@example.com
このemailはname="email"から来ています。一方、id="user-email"はラベルとの関連付けに使われます。
nameとidを同じ文字列にすることはできますが、同じでなければならないわけではありません。
idはページ内で重複させない
idは文書内で一意にします。同じフォーム部品をコピーしたときは、forとidをセットで変更してください。
<label for="work-email">勤務先メールアドレス</label>
<input type="email" id="work-email" name="work_email">
<label for="private-email">個人メールアドレス</label>
<input type="email" id="private-email" name="private_email">
重複したidがあると、ラベルを押したときに意図しない入力欄へフォーカスが移る可能性があります。画面上は似た形に見えても、関連付けは壊れています。
入力欄をlabelの中に入れる方法
labelの内側に入力欄を置くと、forとidを省略した暗黙的な関連付けもできます。
<label>
表示名
<input type="text" name="display_name">
</label>
短いコードで済むため、小規模なフォームでは便利です。ただし、実務では次の理由からforとidを使う明示的な書き方が扱いやすい場面が多くあります。
- ラベルと入力欄をCSS GridやFlexboxで別々に配置しやすい
- HTMLを見たときに関連先が明確になる
- 支援技術との幅広い互換性を確保しやすい
- テンプレートやコンポーネントで構造を変更しやすい
暗黙的な書き方が誤りというわけではありません。レイアウトや実装環境に応じて選べますが、迷ったら明示的な関連付けを選ぶとよいでしょう。
なお、labelの中に別のlabelを入れたり、対象ではない別の入力欄を追加したりしてはいけません。一つのラベルがどの部品を説明しているのか曖昧になる構造は避けます。
最小構成の問い合わせフォームを作る
ここでは、テキスト入力、プルダウン、チェックボックスを含む小さなフォームを作ります。
<form action="/contact" method="post">
<div class="form-field">
<label for="contact-name">お名前</label>
<input
type="text"
id="contact-name"
name="name"
autocomplete="name"
required
>
</div>
<div class="form-field">
<label for="contact-email">メールアドレス</label>
<input
type="email"
id="contact-email"
name="email"
autocomplete="email"
placeholder="例: user@example.com"
required
>
</div>
<div class="form-field">
<label for="contact-category">お問い合わせ種別</label>
<select id="contact-category" name="category">
<option value="product">製品について</option>
<option value="support">サポートについて</option>
<option value="other">その他</option>
</select>
</div>
<div class="form-field">
<label for="contact-message">お問い合わせ内容</label>
<textarea
id="contact-message"
name="message"
rows="6"
required
></textarea>
</div>
<div class="form-check">
<input
type="checkbox"
id="agree-policy"
name="agree"
value="yes"
required
>
<label for="agree-policy">個人情報の取り扱いに同意する</label>
</div>
<button type="submit">入力内容を送信する</button>
</form>
入力例は次のとおりです。
お名前: 山田太郎
メールアドレス: taro@example.com
お問い合わせ種別: サポートについて
お問い合わせ内容: ログイン方法を確認したいです。
個人情報の取り扱い: 同意する
サーバーが受け取る代表的な項目は、次のような組み合わせになります。
name=山田太郎
email=taro@example.com
category=support
message=ログイン方法を確認したいです。
agree=yes
実際のエンコード形式は送信方法やサーバー実装によって変わります。また、HTMLのrequiredやtype="email"による検証だけを信用してはいけません。送信データは改変できるため、サーバー側でも必須項目、文字数、形式を検証してください。
読みやすく配置するCSS
ラベルを入力欄の上に置くと、項目との対応が分かりやすく、狭い画面でも横スクロールが生じにくくなります。
.form-field {
margin-block-end: 1rem;
}
.form-field label {
display: block;
margin-block-end: 0.4rem;
font-weight: 700;
}
.form-field input,
.form-field select,
.form-field textarea {
box-sizing: border-box;
width: 100%;
max-width: 36rem;
padding: 0.65rem;
font: inherit;
}
.form-check {
display: flex;
align-items: start;
gap: 0.5rem;
margin-block: 1rem;
}
.form-check label {
cursor: pointer;
}
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
button:focus-visible {
outline: 3px solid #1a73e8;
outline-offset: 2px;
}
フォーカス枠は、キーボードで現在位置を確認する手掛かりです。デザイン上の理由だけでoutline: noneを指定して消さないようにします。
チェックボックスとラジオボタンの正しいラベル
小さな選択部品ほど、ラベルによってクリック範囲を広げる効果が大きくなります。
チェックボックスは選択肢ごとに関連付ける
<input type="checkbox" id="mail-news" name="topics" value="news">
<label for="mail-news">新着情報</label>
<input type="checkbox" id="mail-event" name="topics" value="event">
<label for="mail-event">イベント情報</label>
二つの入力欄で同じname="topics"を使うのは、同じ種類の送信データとして扱うためです。一方、ラベルが個別の選択肢を指せるように、idはそれぞれ異なる値にします。
ラジオボタンの質問文にはlegendを使う
ラジオボタンでは、個々の選択肢だけでなく「何について選ぶのか」も伝える必要があります。質問全体をfieldsetとlegendでまとめ、各選択肢にlabelを付けます。
<fieldset>
<legend>希望する連絡方法</legend>
<div>
<input
type="radio"
id="contact-by-email"
name="contact_method"
value="email"
checked
>
<label for="contact-by-email">メール</label>
</div>
<div>
<input
type="radio"
id="contact-by-phone"
name="contact_method"
value="phone"
>
<label for="contact-by-phone">電話</label>
</div>
</fieldset>
ここでの役割分担は明確です。
legend: グループ全体の質問「希望する連絡方法」label: 各ラジオボタンの選択肢「メール」「電話」- 共通の
name: 同じグループ内で一つだけ選択できるようにする - 固有の
id: 各ラベルの関連先を区別する
質問文を単なるp要素で置くだけでは、支援技術が選択肢との関係を認識できない場合があります。
placeholderはlabelの代わりにならない
placeholderは入力例を示す補助情報であり、項目名ではありません。 入力を始めると表示されなくなるため、何を入力していたのか確認しにくくなります。
NG例
<input
type="email"
name="email"
placeholder="メールアドレス"
>
見た目には説明があるようでも、常に表示されるラベルがありません。入力済みの値を見直す場面では、項目名が消えています。
改善例
<label for="account-email">メールアドレス</label>
<input
type="email"
id="account-email"
name="email"
placeholder="例: user@example.com"
>
役割を分けるのがポイントです。
label: 入力する情報の名前placeholder: 入力形式の短い例- 補足文: 条件や注意事項
長い入力条件をplaceholderへ詰め込むのも避けます。たとえばパスワード条件は、入力欄の外に常時見える説明として置きます。
<label for="new-password">新しいパスワード</label>
<p id="password-help">
12文字以上で、英字と数字をそれぞれ1文字以上含めてください。
</p>
<input
type="password"
id="new-password"
name="password"
minlength="12"
aria-describedby="password-help"
required
>
aria-describedbyによって、ラベルとは別の補足説明を入力欄に関連付けられます。項目名までaria-describedbyに任せるのではなく、名前はlabel、追加条件は説明文という形で分担します。
必須表示とエラーも入力欄に結び付ける
ラベルがあっても、入力条件やエラーの伝え方が曖昧ではフォームを完了できません。
必須項目は色だけで示さない
赤色だけで必須を表すと、色を区別しにくい利用者には伝わりません。「必須」という文字をラベル内に含めると明確です。
<label for="company-name">
会社名 <span>(必須)</span>
</label>
<input
type="text"
id="company-name"
name="company"
required
>
requiredはブラウザに必須項目であることを伝え、ラベル内の「必須」は人に伝えます。両方に役割があります。
エラー文はaria-describedbyで参照する
検証に失敗した場合は、色や枠線だけでなく、原因と直し方を文章で示します。
<label for="billing-email">請求書送付先メールアドレス</label>
<input
type="email"
id="billing-email"
name="billing_email"
value="user@example"
aria-invalid="true"
aria-describedby="billing-email-error"
>
<p id="billing-email-error">
@以降を含むメールアドレスを入力してください。
</p>
aria-invalid="true"は現在の値が無効であることを示し、aria-describedbyは具体的なエラー文を入力欄に関連付けます。再表示時には、問題のない入力値まで消して再入力させない設計も重要です。ただし、パスワードやカード情報などの機密データを不用意に再表示してはいけません。
よくある失敗と直し方
動かないときは、見た目より先にHTMLの関連付けを確認します。
失敗1:forとnameを合わせている
<label for="email">メールアドレス</label>
<input id="user-email" name="email" type="email">
for="email"が探すのはname="email"ではなく、id="email"です。この例では一致していません。
修正方法は、forとidを同じ値にすることです。
<label for="user-email">メールアドレス</label>
<input id="user-email" name="email" type="email">
失敗2:説明文を隣に置いただけ
<span>電話番号</span>
<input type="tel" name="phone">
人には近く見えても、ブラウザは説明文と入力欄の関係を確定できません。spanをlabelに変え、forとidで結び付けます。
失敗3:コピーしたidが重複している
フォーム部品を複製したら、次の三つをセットで確認します。
labelのfor- 入力欄の
id - 送信データに使う
name
forとidは一組ごとに一致させ、各idはページ内で重複させません。ラジオボタンだけは、同じグループを作るためにnameを共通にします。
失敗4:aria-labelを常に優先する
画面に文字を置けない特殊なボタンなどでは、aria-labelが必要になることがあります。しかし、通常の入力フォームで可視ラベルを消すと、画面を見ている利用者が項目の目的を確認できません。
まずはHTML標準のlabelを使い、可視ラベルを置けない合理的な理由がある場合に限ってARIAによる名前付けを検討します。
失敗5:一つのlabelに操作要素を詰め込む
<label for="agree">
<input id="agree" type="checkbox" name="agree">
規約に同意する
<a href="/terms">規約を読む</a>
</label>
ラベル内にリンクのような別の操作要素を置くと、クリック時の動作が分かりにくくなります。リンクとラベルは分ける方が安全です。
<input id="agree" type="checkbox" name="agree">
<label for="agree">規約に同意する</label>
<p><a href="/terms">利用規約を確認する</a></p>
labelが機能しているか確認する方法
実装後は、コードを眺めるだけでなく実際に操作します。
1. ラベルをクリックする
テキスト入力のラベルをクリックし、入力欄にカーソルが表示されるか確認します。チェックボックスやラジオボタンでは、文字部分を押して選択状態が変わるかを確認します。
2. キーボードだけで操作する
Tabキーで各フォーム部品へ移動し、フォーカス位置が見えるか確認します。チェックボックスはSpaceキー、ラジオボタンは通常、矢印キーで選択できます。
3. HTMLを確認する
各項目について、次を順番に見ます。
- 入力欄に固有の
idがあるか labelのforと入力欄のidが完全に一致しているか- 同じ
idがページ内に複数ないか - 項目の目的がラベルの文言だけで分かるか
- 入力形式やエラーが色だけに依存していないか
4. 自動検査だけで終わらせない
開発者ツールやアクセシビリティ検査ツールは、ラベルの欠落や重複IDを見つける助けになります。ただし、「内容を入力」のようなラベルが利用者にとって十分具体的かどうかは、人が画面の文脈を見て判断する必要があります。
label・ARIA・周辺要素の使い分け
フォームの名前付けでは、HTML標準の要素を出発点にすると判断しやすくなります。
- 一般的な入力欄:
labelを使う - ラジオボタンや関連するチェックボックスの質問:
fieldsetとlegendでまとめる - 入力例:
placeholderを補助的に使う - 文字数や形式などの追加説明: 通常の説明文と
aria-describedbyを使う - 入力エラー: 具体的なエラー文、
aria-invalid、aria-describedbyを組み合わせる - 送信・キャンセル操作: 内容が明確な
buttonを使う - 可視テキストを置けない特殊な部品: 必要性を確認して
aria-labelまたはaria-labelledbyを検討する
ARIAは、不足したHTMLを何でも補うための近道ではありません。labelやbuttonなど目的に合うHTML要素で実装できるなら、まずそれを使います。
実装前後のチェックリスト
最後に、フォームへ項目を追加するときの確認点を整理します。
- 各入力欄に、目的が分かる可視ラベルを付けた
labelのforと入力欄のidを一致させたidをページ内で重複させていないnameを送信データの項目名として別に確認したplaceholderだけで項目名を表していない- 必須や入力形式を色だけに頼らず文章で示した
- ラジオボタンの質問を
fieldsetとlegendでまとめた - ラベルのクリック、キーボード操作、エラー表示を確認した
- ブラウザ側だけでなくサーバー側でも入力を検証する
まず確認したいのは、ラベルの文字をクリックしたときに正しい入力欄が反応するかです。反応しなければ、forとidの不一致やidの重複を調べます。この小さな確認をフォーム部品の作成手順に組み込むだけでも、入力しやすさとアクセシビリティの問題を早い段階で発見できます。
