WCAG 3.3.2: Labels or Instructions
Whenever content requires user input, provide labels or instructions so people know what to enter and how. This Level A criterion is the foundation of accessible forms — a missing or unclear form label is one of the most common accessibility failures on the web, and it blocks screen reader users, voice-control users, and anyone who needs extra guidance from completing a task.
The success criterion, in full
Labels or instructions are provided when content requires user input.
Why labels and instructions matter
A form field with no label is a blank box. A sighted user can often guess its purpose from surrounding layout, but a screen reader user hears only “edit text, blank” — no clue whether to type a name, an email, or a phone number. Voice-control users cannot say “click” the field by name because it has no name. People with cognitive disabilities lose the persistent reminder of what each field is for. The result is abandoned checkouts, failed sign-ups, and forms that simply cannot be completed.
This is not a rare edge case. Missing form input labels is one of the most frequently detected failures across the web — the annual WebAIM Million analysis consistently ranks unlabeled form controls among the top accessibility errors on home pages. Because labels are foundational and the fix is well understood, 3.3.2 is one of the highest-impact, lowest-effort criteria to get right.
What 3.3.2 actually requires
The criterion has two parts — a label and, where needed, instructions:
- 1
Every control that takes input has a label. Text fields, textareas, selects, checkboxes, radio buttons, file inputs, sliders, and switches all need a label that describes what they are for. The label should be present before the user interacts and should stay visible.
- 2
Non-obvious requirements are explained. If a field has a required format (a date as DD/MM/YYYY), a constraint (password must be 12+ characters), or a required/optional status, that information must be available before the user submits — not only afterward as an error message.
- 3
Instructions are positioned where they help. Guidance should appear near or before the control it describes and be programmatically connected with
aria-describedbyso assistive technology announces it with the field.
Note: 3.3.2 only asks that a label or instruction is present. Whether that label is programmatically associated with the control is governed by 1.3.1 Info and Relationships, and whether the control exposes a correct accessible name and role is governed by 4.1.2 Name, Role, Value. A well-built form satisfies all three at once.
Four ways to label a control
There are four reliable techniques, listed roughly in order of preference. The first two use a real, visible <label> and should be your default; the ARIA methods exist for the cases the native element cannot cover.
1. Wrap the control in a <label>
Implicit association — no id needed.
Put the input inside the label element. The browser links them automatically, so you do not need a matching id and for attribute. This is the most resilient method because there is nothing to keep in sync, but it offers less layout flexibility because the label and control share one element.
2. Connect <label for> to an id
Explicit association — the most common and flexible.
Give the input an id and point the label's for attribute at it. Clicking the label focuses (or toggles) the control, and screen readers announce the label when the field receives focus. This is the workhorse pattern: it works with any layout and is supported everywhere.
3. aria-labelledby pointing at visible text
Reuse on-screen text as the accessible name.
When the visible label is some other element — a heading, a table cell, a span — reference its id with aria-labelledby. You can list several ids and they are concatenated in order. Prefer this over aria-label because the name stays visible and is covered by translation and copy edits.
4. aria-label as a last resort
An invisible name when no visible text exists.
aria-label supplies an accessible name directly in markup with no visible counterpart. Use it only when a visible label genuinely is not possible — for example, a search field whose purpose is obvious from a magnifying-glass icon. Because it is invisible, sighted users get no benefit and it is easy for it to drift out of date or escape translation.
Why a placeholder is not a label
The single most common 3.3.2 mistake is using placeholder text in place of a label to save vertical space. It breaks in four ways:
- It vanishes on input. The moment the user types a character, the placeholder disappears — so the reminder of what the field is for is gone exactly when it is needed, which is especially hard for people with memory and attention disabilities.
- It is unreliable as an accessible name. Browser and screen reader support for treating placeholder as the accessible name is inconsistent, so some users get no name at all.
- It usually fails contrast. Default placeholder styling is light gray and commonly falls below the 4.5:1 ratio required by 1.4.3 Contrast (Minimum).
- It looks like a pre-filled value. Users frequently mistake placeholder text for an already-entered answer and skip the field.
Keep a persistent visible label and, if it adds value, use the placeholder for a short example of the expected format (for example, name@example.com) — never as the only label.
Code examples
The default: a visible label tied to the input
An explicit for/id pairing works in every layout and makes the label clickable.
<!-- Explicit association: label[for] -> input[id] -->
<label for="email">Email address</label>
<input type="email" id="email" name="email" autocomplete="email" />
<!-- Implicit association: input nested in label, no id needed -->
<label>
Email address
<input type="email" name="email" autocomplete="email" />
</label>Add instructions with aria-describedby
Format hints, required status, and constraints belong in a hint element that is announced together with the field.
<label for="pwd">Password (required)</label>
<input
type="password"
id="pwd"
name="password"
required
aria-describedby="pwd-hint"
/>
<p id="pwd-hint">Use at least 12 characters, including a number and a symbol.</p>Group related controls with fieldset and legend
A set of radio buttons or checkboxes needs a group label as well as a label on each option.
<fieldset>
<legend>Shipping method</legend>
<label>
<input type="radio" name="ship" value="standard" />
Standard (3–5 business days)
</label>
<label>
<input type="radio" name="ship" value="express" />
Express (next business day)
</label>
</fieldset>Accessible React field with label and hint
A reusable field that always renders a visible label, wires up the hint, and exposes required state to assistive technology.
function Field({ id, label, hint, required, ...props }) {
const hintId = hint ? `${id}-hint` : undefined
return (
<div>
<label htmlFor={id}>
{label}{required && <span aria-hidden="true"> *</span>}
{required && <span className="sr-only"> (required)</span>}
</label>
<input
id={id}
required={required}
aria-describedby={hintId}
{...props}
/>
{hint && <p id={hintId}>{hint}</p>}
</div>
)
}An icon-only control that needs an invisible name
When a visible label genuinely is not feasible — a compact search box marked only by an icon — supply the name with aria-label.
<input
type="search"
name="q"
aria-label="Search articles"
placeholder="Search…"
/>Common mistakes
- Using a placeholder as the only label. It disappears on input, often fails contrast, and is not reliably exposed as the accessible name.
- A visible label that is not associated with its control — sitting next to the input with no for/id link, so screen readers never announce it.
- Mismatched for and id values (a typo, or an id reused on the page) that silently break the association even though the markup looks right.
- Marking required fields with a red asterisk or color alone, with no text equivalent and no required / aria-required attribute.
- Putting format instructions only in an error message that appears after submission, instead of before the user fills the field.
- Radio or checkbox groups with no fieldset and legend, so each option is announced without the question it answers.
- Relying on a nearby heading or table position for meaning without connecting it to the field with aria-labelledby or aria-describedby.
How to test for 3.3.2
- 1
Click each visible label
Clicking a properly associated text-input label should move focus into the field; clicking a checkbox or radio label should toggle it. If nothing happens, the label is not associated.
- 2
Tab through with a screen reader
Using NVDA, JAWS, or VoiceOver, tab to every control and confirm a clear name is announced — not 'edit text, blank'. Listen for required state and any hint text too.
- 3
Inspect the accessible name
In browser DevTools, check the Accessibility pane for each control's computed name and description. Confirm the name comes from a real label, not a placeholder.
- 4
Run automated checks
axe DevTools, Lighthouse, and WAVE flag missing and empty form labels reliably — this is one failure automation catches well. Treat a clean automated pass as the floor, not the finish line.
- 5
Check instructions and required hints
Verify that format requirements and required status are visible before submission and are connected with aria-describedby so they are announced with the field.
Audit a live form with the URL Accessibility Auditor and learn the manual steps in the Screen Reader Testing Guide.
Related success criteria
1.3.1 Info and Relationships — A
Requires that the label–control relationship is programmatically determinable. 3.3.2 says a label exists; 1.3.1 says it is wired up correctly.
4.1.2 Name, Role, Value — A
Governs whether each control exposes a correct accessible name and role to assistive technology — the engine that turns a label into a spoken field name.
3.3.1 Error Identification — A
The sibling forms criterion: when input is rejected, the error must be identified in text. Clear labels up front reduce errors; 3.3.1 handles them when they happen.
2.4.6 Headings and Labels — AA
Raises the bar at Level AA: labels must not only exist but also be descriptive enough to convey the field's topic or purpose.
Browse every criterion in the WCAG Success Criteria hub or work through the full WCAG 2.2 checklist.
Frequently asked questions
What does WCAG 3.3.2 Labels or Instructions require?
WCAG 3.3.2 requires that labels or instructions are provided when content requires user input. In practice this means every form control — text inputs, selects, checkboxes, radio buttons, file pickers, and so on — must have a label that describes what to enter, and any non-obvious requirements (a date format, a password rule, which fields are required) must be communicated as instructions. It is a Level A success criterion, the lowest and most essential conformance level.
Is a placeholder the same as a label?
No. A placeholder is not a label and does not satisfy 3.3.2 on its own. Placeholder text disappears the moment a user starts typing, so it cannot serve as a persistent label; it is not reliably exposed to all assistive technology as the accessible name; and its low-contrast styling commonly fails 1.4.3 Contrast (Minimum). Use a real, persistent visible label and reserve the placeholder for an optional example of the expected input.
Do labels have to be visible, or is aria-label enough?
WCAG 3.3.2 at Level A is satisfied by a programmatically associated label even if it is provided only with aria-label, but a visible label is strongly preferred and is what most teams should ship. Visible labels help sighted users — including people with cognitive disabilities — and a separate criterion, 2.4.6 Headings and Labels (also AA), expects labels to be descriptive. Reserve invisible aria-label names for the rare cases where a visible label truly is not feasible.
How do I mark required fields accessibly?
State the requirement in a way that is both visible and programmatic. Add the word 'required' or a legend explaining the asterisk to the visible label, and expose the state to assistive technology with the HTML required attribute (or aria-required="true" on custom controls). Do not rely on a red asterisk or color alone — that fails users who cannot perceive the color and is not announced unless the asterisk's meaning is in the accessible name or an associated instruction.
How is 3.3.2 different from 1.3.1, 4.1.2, and 3.3.1?
They overlap but test different things. 3.3.2 Labels or Instructions is about whether a label or instruction is present and understandable for input. 1.3.1 Info and Relationships is about whether that label is programmatically associated with its control. 4.1.2 Name, Role, Value is about whether the control exposes a correct accessible name and role to assistive tech. 3.3.1 Error Identification covers what happens after a mistake. A missing form label often triggers failures under several of these at once.
How do I label a group of radio buttons or checkboxes?
Wrap the group in a fieldset and give it a legend that asks the overall question (for example, 'Shipping method'). Each individual radio or checkbox still needs its own label. The legend provides the group-level context that screen readers announce alongside each option, so a user hears 'Shipping method, Standard, radio button' rather than just 'Standard'.