# The value of the “for” attribute of the “label” element must be the ID of a non-hidden form control.

> Canonical HTML version: https://rocketvalidator.com/html-validation/the-value-of-the-for-attribute-of-the-label-element-must-be-the-id-of-a-non-hidden-form-control
> Attribution: Rocket Validator (https://rocketvalidator.com)
> License: CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/)

The `<label>` element associates descriptive text with a specific form control, enabling users to click the label to focus or activate the associated input. The `for` attribute creates this link by referencing the `id` of the target form control. When the referenced `id` doesn't correspond to a valid, non-hidden form control, the label becomes orphaned — it isn't associated with anything meaningful.

The W3C validator raises this error in several scenarios:

- The `for` attribute references an `id` that doesn't exist in the document.
- The `for` attribute references an element that isn't a labelable element (such as a `<div>` or `<span>`).
- The `for` attribute references an `<input type="hidden">`, which is not a visible form control and cannot be labeled.
- There's a typo or mismatch between the `for` value and the intended element's `id`.

Labelable elements in HTML include `<input>` (except `type="hidden"`), `<select>`, `<textarea>`, `<button>`, `<meter>`, `<output>`, and `<progress>`.

This matters for **accessibility** because screen readers rely on the `for`/`id` association to announce what each form control represents. Without a valid association, users who depend on assistive technology may not understand what a form field is asking for. It also impacts **usability** — a properly linked label expands the clickable area for the form control, making it easier to interact with, especially on touch devices and for users with motor impairments.

To fix this issue, verify that the `for` attribute value exactly matches the `id` of a visible, labelable form control. If you're labeling a hidden input, consider whether the label is necessary at all (hidden inputs are not user-facing). If the target element isn't a form control, either change it to the appropriate form element or use a different approach like `aria-labelledby`.

## Examples

### ❌ `for` references a non-existent ID

```html
<label for="username">Username</label>
<input id="user-name" type="text">
```

The `for` value `"username"` doesn't match the input's `id` of `"user-name"`.

### ✅ Fixed: matching `for` and `id`

```html
<label for="username">Username</label>
<input id="username" type="text">
```

### ❌ `for` references a hidden input

```html
<label for="token">Token</label>
<input id="token" type="hidden" value="abc123">
```

An `<input type="hidden">` is not a visible form control and cannot be labeled.

### ✅ Fixed: remove the unnecessary label

```html
<input id="token" type="hidden" value="abc123">
```

Hidden inputs don't need labels since users never interact with them directly.

### ❌ `for` references a non-labelable element

```html
<label for="info">Information</label>
<div id="info">Some details here</div>
```

A `<div>` is not a labelable element, so the `for` association is invalid.

### ✅ Fixed: use a proper form control or implicit labeling

```html
<label for="info">Information</label>
<textarea id="info"></textarea>
```

### ❌ `for` references an element inside another form control

```html
<label for="opt">Choose one</label>
<select>
  <option id="opt" value="a">Option A</option>
</select>
```

An `<option>` element is not a labelable element. The label should point to the `<select>`.

### ✅ Fixed: reference the `<select>` element

```html
<label for="choice">Choose one</label>
<select id="choice">
  <option value="a">Option A</option>
</select>
```

### Using implicit labeling as an alternative

Instead of using the `for` attribute, you can wrap the form control inside the `<label>` element. This creates an implicit association without needing `for` or `id` at all:

```html
<label>
  Age
  <input type="number">
</label>
```

This approach avoids the `for`/`id` mismatch problem entirely and is equally valid for accessibility.
