Attach A JSX label To Its Control

ID

javascript.jsx_label_for_input

Severity

low

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Reliability

Language

JavaScript

Tags

accessibility, jsx, reliability

Description

Reports a JSX <label> that names no control: it neither carries htmlFor nor wraps one.

Rationale

A label is only a label once it is attached to a control. Unattached, it is styled text: a screen reader announces the field as unlabelled, clicking the text does not focus the field, and the click target stays as small as the control itself.

The two ways to attach one are htmlFor pointing at the control’s id, and nesting the control inside the label. With neither, the association exists only in the layout.

This is the label’s side of the association, which is the side JSX gets wrong: htmlFor is the JSX spelling of HTML’s for, and a label written with for silently sets a non-standard DOM attribute. Both spellings are accepted here, because a label that writes one of them has declared its intent and the wrong spelling is a different defect.

A nested component (<TextField />, <Select />) counts as a control: its rendered markup is not visible here and it very often is one, so reporting it would be a guess. Only the DOM <label> tag is judged, and an element that spreads an object into its attributes is left alone, since htmlFor may arrive at runtime.

The check runs from the label rather than from the input, because in a component tree the input is frequently in another file — the label is the only end of the association a single compilation unit can see.

<label>Email</label>                                // FLAW - names nothing
<label className="field"><span>Email</span></label> // FLAW - still no control

<label htmlFor="email">Email</label>                // OK - names by id
<label>Email<input name="email" /></label>          // OK - wraps the control
<label>Email<TextField /></label>                   // OK - a component may be one

Remediation

Point the label at its control with htmlFor={id}, giving the control the matching id; the id has to be unique in the document, so derive it from a prop or a generated identifier rather than hard-coding one in a reusable component. Or nest the control inside the label, which needs no id at all and is the smaller change. When the text is not labelling anything, use a <span> or a <div>, which carry no label role to leave unattached.

© 2026 Xygeni. All rights reserved