Skip to content

Labels & Form Accessibility: <label>, for, and id

The form you built in Lesson 01 has two unlabeled text fields. A sighted user might guess what each one is for — but a screen reader user has no way to know. Labels fix that.

A <label> tells users (and assistive technologies) what an input is for. Without labels:

  • Screen readers announce the input as “text field” with no context
  • Clicking near an input does not focus it
  • The form is harder to use for everyone

With labels:

  • Screen readers announce “Name, text field” or “Email address, text field”
  • Clicking the label focuses the input — larger click target
  • The form is accessible and clear

The link between a <label> and its <input> is made with two attributes:

  • for on the <label> — contains the id of the input it labels
  • id on the <input> — a unique identifier that matches the for value
<label for="user-name">Name</label>
<input type="text" id="user-name" name="name">

The for value (user-name) must exactly match the id value (user-name). If they do not match, the association breaks and the label does nothing useful.

<form>
<label for="user-name">Name</label>
<input type="text" id="user-name" name="name">
<label for="user-email">Email address</label>
<input type="email" id="user-email" name="email">
</form>

Each label sits above its input. The browser renders them on separate lines by default because <label> is an inline element — but that is fine here. CSS controls the layout later.

An alternative is to nest the <input> directly inside <label>. This creates the association automatically without needing for and id:

<label>
Name
<input type="text" name="name">
</label>

Both patterns are valid. The explicit for/id pattern is more common in real codebases because it keeps labels and inputs separate, making the HTML easier to style independently. Use whichever your project or team prefers — but be consistent.

placeholder text (which you will learn in Lesson 05) appears inside an input as hint text and disappears when the user starts typing. It is not a replacement for a label.

A placeholder tells the user what format to use. A label tells the user what the field is for. Both can exist together:

<label for="user-email">Email address</label>
<input type="email" id="user-email" name="email" placeholder="you@example.com">

Never use a placeholder as the only identifier for a field — the text disappears the moment the user starts typing, leaving them with no reminder of what they were filling in.

Open index.html in VS Code.

Find the <form> you added in Lesson 01. It currently has two unlabeled inputs. You are going to add a <label> for each one.

  1. Before the <input type="text">, add a label connected with for and id:
<label for="contact-name">Your name</label>
<input type="text" id="contact-name" name="name">
  1. Before the <input type="email">, add a label:
<label for="contact-email">Email address</label>
<input type="email" id="contact-email" name="email">

Your form section should now look like this:

<section>
<h2>Contact</h2>
<form>
<label for="contact-name">Your name</label>
<input type="text" id="contact-name" name="name">
<label for="contact-email">Email address</label>
<input type="email" id="contact-email" name="email">
</form>
</section>
  1. Save and open index.html in your browser. Click the label text — the corresponding input should become focused. That click-to-focus behavior confirms the association is working.
  • <label> identifies what an input is for. Every input should have one.
  • The for attribute on <label> must match the id attribute on <input>.
  • Clicking a label focuses its associated input — a larger, more accessible click target.
  • Screen readers read the label text aloud when the user focuses the input.
  • Labels are not placeholders. A placeholder provides formatting hints; a label identifies the field.