Well-labeled form controls are the backbone of accessible web design. When users interact with an input, they should know exactly what information is expected—whether they rely on sight, screen readers, or voice input. Clear, consistent labeling improves usability for everyone, reduces errors, and ensures compliance with accessibility standards such as WCAG.
The challenge is that HTML offers multiple ways to “label” an input—<label>
, placeholder
, title
, aria-label
, and aria-labelledby
. While they may look interchangeable, each serves a specific role, and using them incorrectly often creates redundancy or confusion. The key is knowing when to use which attribute and how they interact.
Below is a consolidated resource for web developers on properly labelling form controls in HTML for accessibility. It covers the “why”, best practices, common pitfalls, attribute hierarchy, and concrete patterns to follow.
Why labels matter
- The Web Content Accessibility Guidelines (WCAG) require form controls to have both a label (visible) and a name (what assistive tech like screen-readers understand). These should match or at least be consistent.
- Visible labels help all users: sighted, cognitive, motor‐impaired. They improve clarity, reduce errors, and help users know what to enter.
- Programmatic labels (via
<label>
,aria-labelledby
, etc.) are essential for assistive technologies to properly expose the name, role, and state of inputs. Without these, screen readers often announce something generic like “edit field” with no context.
Attribute hierarchy for accessible names
When multiple possible sources of a “name” exist (label, placeholder, title, aria-label, aria-labelledby), browsers and assistive technologies follow rules to pick one. Knowing the hierarchy helps avoid unintentional outcomes.
Rough order (from highest priority / strongest):
aria-labelledby
— refers to visible text elsewhere in the page; best when a label or text grouping already exists.aria-label
— used when no visible label text is present (e.g. icon-only buttons). But if you already have a<label>
, avoid overriding it.<label>
element (explicitfor="id"
) or implicit wrapping of control in<label>
— the normal, preferred way. It is visible and programmatically associated.title
attribute — weak: inconsistent support, often only visible on hover, often ignored by some assistive tech. Should rarely be relied upon for critical labeling.placeholder
attribute — not a substitute for a label. It is transient (disappears when user types), often low contrast, and may be omitted by some screen readers. Use only for hinting input format, not for essential identity.
Best practices / patterns to follow
Here are concrete guidelines to ensure your form controls are well-labelled and accessible:
Practice | What to Do | Why It Helps |
---|---|---|
Always include a visible <label> for each input | Use <label for="inputID"> with a matching id on the input, or wrap the input inside <label> . | Ensures the label is read by assistive tech and seen by sighted users. Improves usability by making the label clickable, which sets focus on the input. |
Use aria-describedby for supplementary instructions | Add aria-describedby="hintID" on the input and place extra guidance in an element with that id . | Keeps the main label concise while still giving screen readers access to hints such as format or required rules. Maintains clarity between “what the field is” and “how to fill it.” |
Reserve aria-label / aria-labelledby for when no visible label is possible | Use them only for icon-only buttons, custom widgets, or when design constraints prevent visible text. Prefer aria-labelledby if text already exists on screen. | Provides an accessible name when no visible label is available. Prevents overwriting or duplicating a perfectly good <label> . |
Avoid relying on the title attribute for labels | Do not use title as the only way to identify an input. If used, restrict it to supplementary, non-essential information. | title is inconsistently supported by screen readers, often hidden on touch devices, and hard to discover. Not dependable for conveying critical information. |
Use placeholder only for hints or examples | Write placeholder text that shows expected format or example values (e.g., user@example.com ), not the field’s name. | Prevents confusion when the placeholder disappears on input. Keeps the accessible name consistent while still offering useful context. |
Mark required fields clearly and handle errors accessibly | Indicate required fields with visible text (e.g., “Required”) and link error messages using aria-describedby . | Helps all users understand constraints. Screen readers can announce errors when focus returns to the field, ensuring no information is lost. |
Group related fields with <fieldset> and <legend> | Wrap sets of related inputs (like radio buttons or checkboxes) in a <fieldset> , with a <legend> describing the group. | Provides essential context so assistive tech announces the group meaningfully (e.g., “Choose a shipping option”). Improves comprehension for sighted and non-sighted users alike. |
Common mistakes to avoid
- Duplicating the same label text in
<label>
,aria-label
,title
, andplaceholder
. Leads to redundant reads by screen readers. - Letting placeholder be the only visible label. Once the user begins typing, the placeholder disappears; low contrast or tiny placeholder text compounds problems.
- Using
aria-label
that contradicts or omits visible label. For example, the visible label says “First name”,aria-label
says “Your name” → assistive tech only announces “Your name”, confusing users who see “First name”. Violates “Label in Name” WCAG criterion. - Believing
title
reliably substitutes for labels. Many screen readers ignoretitle
, or it may only be read on hover/focus. On mobile, hover doesn’t exist. - Over-using ARIA: adding
aria-label
,aria-labelledby
, etc., when a standard HTML<label>
would suffice, complicating maintenance and possibly reducing accessibility.
Example patterns (good vs bad)
Here are side-by-side examples to illustrate the right way and wrong way.
Bad:
<label for="email">Email</label>
<input type="email" id="email"
aria-label="Email"
placeholder="Email"
title="Email">
Issues:
- Three sources of “Email” text:
<label>
,aria-label
,placeholder
,title
→ redundant, possible confusion. placeholder
disappears once input starts.title
not reliably read; may be inaccessible on some devices.
Good:
<label for="email">Email address</label>
<input type="email" id="email" placeholder="user@example.com">
Variations where extra hints are needed:
<label for="dob">Date of birth</label>
<input type="text" id="dob" aria-describedby="dob-format">
<span id="dob-format">Format: YYYY-MM-DD</span>
Or, for an icon-only button:
<button aria-label="Close dialog">
<svg aria-hidden="true" focusable="false">
<!-- icon markup -->
</svg>
</button>
Checklist for developers
Before deploying a form control, run through this checklist:
- Does each input have a visible
<label>
? - Is the
for
-attribute on label andid
on input correctly matched? - Are supplementary hints/instructions needed? If yes, are they linked with
aria-describedby
? - Is there any
aria-label
,title
,placeholder
in place? If so, are they needed, and do they duplicate label text or conflict? - Does the visible label match (or is included in) the accessible name (especially when using ARIA)?
- Do required fields and error messages communicate clearly (visibly and programmatically)?
- Test with a screen reader (e.g. NVDA, VoiceOver) and keyboard only; test on mobile.
Summary
- Prefer visible, properly associated
<label>
elements for form controls. - Use
aria-label
oraria-labelledby
only when no visible label is possible. - Use
placeholder
only for hints, not for essential labeling. - Use
title
very sparingly; never rely on it for critical information. - Always ensure that what users see visually aligns with what assistive technologies announce (accessible name).