Standards · ARIA

Property Relationship

aria-labelledby

References one or more element IDs whose visible text becomes the accessible name of this element. Preferred over aria-label when on-screen text already describes the control.

When to use

When a visible piece of text on the page already describes the element — a heading above a dialog, a column header above a cell, a paragraph that introduces a region. aria-labelledby points at that text so the screen reader announces it as the element’s accessible name. The user hears exactly what a sighted user reads.

The native HTML equivalent is <label for="…"> on form inputs. aria-labelledby extends the same idea to any role that supports a name.

How it behaves

The value is a space-separated list of element IDs. The AT collects the text content of every referenced element, in order, joins them with spaces, and uses the result as the accessible name. References to hidden elements (display: none, hidden) still contribute their text — the element only needs to be in the DOM.

aria-labelledby takes precedence over aria-label, which in turn takes precedence over visible inner text. So if you point at the visible heading, you do not also need an aria-label.

To keep the relationship valid: the referenced IDs must exist on the page, must be unique, and the text inside them must stay meaningful. If you rerender a tab panel and reuse IDs, double-check that the new content still describes the labelled element.

Common failures

  • Pointing at an ID that does not exist (typo, element removed, component unmounted). The relationship silently fails and the element ends up unnamed.
  • Reusing the same ID twice on the page — only the first match counts.
  • Referencing an element whose text is empty or whitespace-only.
  • Concatenation in the wrong order: aria-labelledby="surname firstname" produces “Smith John” when you wanted “John Smith”.
  • Pointing at a generic <div> containing a long paragraph — the entire paragraph becomes the name. Names should be short; long context belongs in aria-describedby.
  • Forgetting to update the referenced text when localizing — names get out of sync with the visible UI.

Example

<h2 id="billing-heading">Billing address</h2>
<div role="group" aria-labelledby="billing-heading">
  <label>
    Street
    <input type="text" autocomplete="street-address">
  </label>
  <!-- … -->
</div>

<!-- Two IDs concatenated for a "first + last name" pattern -->
<span id="first">First name</span>
<span id="last">(required)</span>
<input type="text" aria-labelledby="first last">