skip to content

In an HTML form, what are the two ways to associate a <label> element with an input, and what does that association actually give the user?

level: juniorimportance: must knowfreq 80%

answer

  1. two ways, not one
  2. explicit versus wrapping
  3. for matches id, never name
  4. label text becomes the hit target
  5. one label, one control

basics

~20 s

Two ways: an explicit label whose for attribute holds the input's id, or a label that wraps the input. Either one names the control for assistive technology and makes clicking the label text focus or toggle that control.

solid answer

~50 s

There are two associations. **Explicit**: `<label for="email">Email</label>` plus `<input id="email">` — `for` must match the control's `id`, not its `name`. **Implicit**: put the control inside the label, `<label>Email <input type="email"></label>`, and the label binds to its first labelable descendant, so no id is needed. Either form does the same three things: it gives the control its accessible name so a screen reader announces "Email, edit text" instead of just "edit text"; it forwards clicks and taps from the label text to the control, which is why tapping the word next to a checkbox toggles it; and it survives layout changes, because the relationship is in the markup rather than in visual proximity. Only labelable elements can be labelled — `input` (except `type="hidden"`), `select`, `textarea`, `button`, `output`, `meter`, `progress`. A label points at exactly one control.

code

html · 13 lines
html
<!-- Explicit: for matches the control's id -->
<label for="email">Email address</label>
<input type="email" id="email" name="email">

<!-- Implicit: the label wraps the control, no id needed -->
<label>
  Email address
  <input type="email" name="email">
</label>

<!-- Broken: for points at the name, so nothing is associated -->
<label for="email">Email address</label>
<input type="email" id="user-email" name="email">

go deeper

for a junior

Know both forms cold and be able to type them: for pointing at the input's id, or the label wrapping the input. Say plainly that for matches id, never name.

for a middle

Explain what the association produces — accessible name, click forwarding to the control, independence from visual layout — and say which of the two forms you would choose in repeated markup and why.

for a senior

Show how you keep labelling correct at scale: unique ids or wrapping in generated rows, a review habit of writing the label before the field, and how you would detect unlabelled controls across an existing codebase.

for a principal

Own the tradeoff between a shared field component that guarantees association and hand-written markup that gives teams freedom. Be able to argue why labelling belongs in a default rather than in a review checklist.

## What "association" means Putting text beside a form field makes it look labelled. It does not make it labelled. A visual arrangement is invisible to the accessibility tree, to the browser's click-forwarding logic, and to anything that reorders the page. Association is a relationship expressed in the markup between a `<label>` element and one *labelable* control, and HTML gives you two ways to express it. ## Explicit association: for + id ```html <label for="email">Email address</label> <input type="email" id="email" name="email"> ``` The `for` attribute holds the **id** of the control. Two things people get wrong here: they point `for` at the `name` attribute, and they assume any id will do. `name` is what the form submits under; `id` is the document-unique handle `for` resolves against. Those two attributes frequently hold the same string, which is exactly why the mistake survives — it works until the day they differ. The explicit form is the one to reach for when the label and the field are separated in the markup by wrappers, error text, or a grid cell, because it does not constrain where either element sits. ## Implicit association: wrapping ```html <label> Email address <input type="email" name="email"> </label> ``` A `<label>` with no `for` attribute labels its **first labelable descendant**. No ids are involved, so nothing can drift out of sync and nothing has to be made unique. That property matters a lot in repeated markup — rows in a table, items rendered from a list — where handing every row the same id is a very common defect. The cost is structural: the control must live inside the label element. If your markup or your styling needs the text and the field in separate containers, use the explicit form instead. You may see both used at once (`<label for="x">…<input id="x"></label>`). That is legal as long as `for` points at the wrapped control itself; pointing it at a *different* control while wrapping one is a genuine conflict and should be avoided. ## What the association buys you **An accessible name.** The label's text becomes the control's name in the accessibility tree. A screen reader user hears "Email address, edit text" rather than "edit text", and voice-control users can say "click Email address". An unlabelled input is announced by its role alone, which tells the user nothing about what to type. **Click forwarding.** Clicking or tapping an associated label activates the control: text and number fields take focus, checkboxes and radios toggle, selects open. This is why a properly labelled checkbox has a hit target the size of its label text instead of a 13-pixel box — an accessibility win that also measurably helps everyone on a phone. **Durability.** Because the relationship lives in the markup, it does not break when CSS moves the label above, beside, or visually away from the field. ## What breaks it - `for` referencing an id that does not exist, or that belongs to a `<div>` or `<span>`. There is no association; the label is inert text. - Duplicate ids in the document. `for` resolves to the first match in tree order, so later fields end up unnamed and their labels focus the wrong control. - Trying to label two controls with one label. `for` takes a single id, and a wrapping label binds only its first labelable descendant. "Name" above a first-name and last-name pair needs two labels — or a `<fieldset>` with a `<legend>` when the shared text is really a group heading. - Using a non-labelable element. A `<div role="textbox">` is not labelled by a `<label>`; only `input` (other than `type="hidden"`), `select`, `textarea`, `button`, `output`, `meter`, and `progress` participate. ## The habit to build Write the label first, then the control. Every control that a user types into or chooses from gets one. If a design has no room for visible label text, that is a design conversation, not a licence to ship an unnamed field — the label element can still be present and positioned off-screen, and the field keeps its name, its click target, and its meaning.

  • Can a single <label> name two inputs — say one "Name" label over first-name and last-name fields?
    No. `for` takes exactly one id, and a wrapping label binds only its first labelable descendant. Give each field its own label ("First name", "Last name"). When the shared text is genuinely a heading for the pair, that is a grouping job: wrap them in a `<fieldset>` and put the shared text in its `<legend>`.
  • What happens if for points at an id that does not exist, or at a <div>?
    Nothing associates. The label renders as ordinary text: no click forwarding, and the control has no accessible name from it. Browsers do not warn, so the field looks fine and is silently unnamed. Only labelable elements participate — `input` (except `type="hidden"`), `select`, `textarea`, `button`, `output`, `meter`, `progress`.
  • If a design leaves no room for visible label text, what do you do?
    Keep the `<label>` element in the markup and position it off-screen with CSS rather than deleting it. The control keeps its accessible name and the markup stays honest. Dropping the label to save space produces a field that assistive technology announces only by role, which is the defect the label exists to prevent.

saying these in an interview costs you the question

  • The for attribute should match the input's name
  • Putting the text right next to the field is enough
  • One label can cover several related inputs
  • Only screen reader users benefit from a label
  • A wrapping label still needs matching for and id

context