aria-labelledby vs. aria-describedby: Differences and Usage
AI generated
A11Y
WCAG
Accessibility · ARIA · WCAG · Screen Readers
aria-labelledby vs. aria-describedby
Differences and usage for screen reader users

Mixing up aria-labelledby and aria-describedby causes screen readers to announce buttons without a name or swallow error messages entirely. This article explains the difference between the accessible name and the accessible description, walks through the WAI-ARIA name computation, shows how to reference multiple ids, and covers the most common mix-ups using real form and dialog examples.

12 min. read aria-labelledby · aria-describedby · Accessible Name WCAG 2.2 · NVDA · VoiceOver · JAWS

1. Accessible name vs. accessible description

Every interactive element in the accessibility tree carries two separate text sources: the accessible name and the accessible description. The name answers the question of what an element is or does, such as "Start search" on a button. The description supplies additional context that is read after the name and role, such as "Opens advanced search in a new panel". Screen readers announce elements in a fixed order: first the name, then the role, then the state, and optionally the description last.

aria-labelledby controls the name, aria-describedby controls the description. Both attributes reference the ids of other elements in the document and adopt their text content instead of carrying literal text in the attribute value itself. Swapping these two roles produces bugs that are invisible to sighted users: the button looks correctly labeled, but the screen reader reads the wrong text at the wrong position or skips the name entirely. This exact mix-up is one of the most common accessibility defects in custom-built forms and components.

2. aria-labelledby: how screen readers compute the name

aria-labelledby has the highest priority in the name computation and overrides aria-label, a native <label> element, and the visible text content. The attribute value is a space-separated list of ids. The browser collects the text content of each referenced element, concatenates it in the order given, and exposes the result to the accessibility tree as the name. This works even when the referenced element is not itself interactive, such as a heading or a plain span.

A common use case is reusing text that already exists on the page as the name for an additional control, such as an icon button next to a product card. Instead of duplicating the card title as a redundant aria-label string, the button references the heading's id directly. If the title changes dynamically via JavaScript later, the name stays in sync automatically because both sources point at the same text node. Important: an element hidden with display:none is still evaluated for name computation as long as aria-labelledby explicitly points to it. That is deliberately specified behavior of the name computation algorithm.