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 |
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.