Skip to main content
Back to module
Accessible & Responsive Interfaces · Accessibility Essentials

Labels and ARIA

Reading42mLesson 4 of 4 in this module

Give every control an accessible name and use ARIA only when HTML cannot do the job.

Why this matters

Every control needs an accessible name: the text a screen reader announces and the words a voice control user says ("click Search"). WCAG 4.1.2 Name, Role, Value and 1.3.1 Info and Relationships (both Level A) require it, and missing names are among the most common failures automated tools find. ARIA (Accessible Rich Internet Applications) is the toolkit for filling gaps HTML cannot, but used carelessly it makes pages worse.

Where accessible names come from

The browser computes a name for each element in a fixed priority order (simplified):

  1. aria-labelledby (points at other elements' ids; their text becomes the name)
  2. aria-label (a string)
  3. The native label: <label> for inputs, alt for images, <caption> for tables, <legend> for fieldsets
  4. The element's text content (for buttons, links and headings)
  5. title (a weak last resort; avoid relying on it)

You can see the result in Chrome or Firefox DevTools: Inspect an element and open the Accessibility pane.

Labels for form fields

Always start with a visible <label>:

<label for="email">Email address</label>
<input id="email" name="email" type="email" autocomplete="email" required aria-describedby="email-hint">
<p id="email-hint">We only use this to send your receipt.</p>
  • for/id links the label, so clicking the label focuses the input and the name is "Email address".
  • Placeholders are not labels. They disappear when you type, are often low contrast, and are not reliably announced.
  • aria-describedby adds a description, announced after the name: perfect for hints and error messages.
  • required is native and exposed to assistive technology; you do not need aria-required as well.
  • autocomplete helps everyone and supports WCAG 1.3.5 Identify Input Purpose (AA).

Group related controls such as radio buttons with <fieldset> and <legend>.

Icon-only buttons

A magnifying-glass button with only an SVG has no name; a screen reader says "button". Two good fixes:

<!-- Option 1: aria-label, and hide the decorative icon -->
<button type="submit" aria-label="Search">
  <svg aria-hidden="true" focusable="false">...</svg>
</button>

<!-- Option 2: visually hidden text (also translated by browser translation tools) -->
<button type="submit">
  <svg aria-hidden="true" focusable="false">...</svg>
  <span class="visually-hidden">Search</span>
</button>

If a control has visible text, the accessible name should contain that text (WCAG 2.5.3 Label in Name), so voice users can say what they see. Do not put aria-label="Submit form" on a button that reads "Send".

Images

  • Informative image: alt describes what it conveys (alt="Acme Tools logo", not alt="image").
  • Decorative image: alt="" so screen readers skip it. Leaving alt out entirely makes some screen readers read the file name.
  • Image inside a link: the alt describes the link's destination.

The W3C's alt decision tree is worth bookmarking.

The rules of ARIA

The W3C's Using ARIA note sets out five rules. The first is the one people quote:

  1. If a native HTML element has the semantics and behaviour you need, use it instead of re-purposing an element and adding ARIA.
  2. Do not change native semantics unless you really have to (no <h2 role="tab">; wrap or restructure instead).
  3. All interactive ARIA controls must be keyboard operable.
  4. Do not use role="presentation" or aria-hidden="true" on a focusable element.
  5. All interactive elements must have an accessible name.

ARIA only changes what assistive technology is told. It adds no behaviour. <div role="button"> announces "button" but still cannot be focused or activated with Enter and Space unless you add tabindex="0" and key handlers yourself. A real <button> does all of that already. This is why audits regularly find that pages with ARIA have more errors than pages without it.

ARIA you will actually use

AttributeUse it for
aria-label, aria-labelledbyNaming controls with no visible label, or landmarks (<nav aria-label="Breadcrumb">)
aria-describedbyHints and error messages
aria-expanded, aria-controlsDisclosures, menus, accordions
aria-current="page"The current link in navigation
aria-hidden="true"Hiding decorative icons from assistive technology
aria-live="polite", role="status"Announcing "Saved" or "3 results" without moving focus (4.1.3)
aria-invalid="true"Marking a field with an error

For complex widgets (tabs, comboboxes, menus, tree views), follow the ARIA Authoring Practices Guide and test with real screen readers; the patterns include required keyboard behaviour, not just attributes.

Worked example: fixing a newsletter form

Before: <input placeholder="Email">, a hint in a <small> floating nearby, a <div role="button" onclick="subscribe()">Subscribe</div>, and a decorative swoosh image with no alt.

After: a visible <label for="email">, aria-describedby linking the hint, a real <button type="button">Subscribe</button> (the role attribute removed), and alt="" on the swoosh. Four changes, every one of them plain HTML except aria-describedby.

Common mistakes

  • Placeholder text as the only label.
  • aria-label on a <div> or <span> with no role: many screen readers ignore it there.
  • Redundant ARIA: <button role="button">, <nav role="navigation">. Harmless at best, noise at worst.
  • aria-hidden="true" on something that can still receive focus.
  • Names that do not match the visible text.

Quick recap

  • Every control needs an accessible name; check it in the DevTools Accessibility pane.
  • Prefer visible <label>s, button text and alt; use aria-label/aria-labelledby when there is no visible text.
  • aria-describedby for hints and errors.
  • First rule of ARIA: use native HTML. ARIA changes announcements, not behaviour.

Try it

Open the Do tab and fix the labels and ARIA in a newsletter form.

Also in this lesson: