Understanding aria-label vs aria-labelledby vs aria-describedby
These three ARIA attributes help provide accessible names and descriptions to elements, especially for screen reader users. Each has a specific role.
aria-label – Provides an accessible name directly as text when no visible label is present (e.g., an icon-only button with aria-label="Close").
aria-labelledby – Provides the accessible name by referencing the ID of another element (usually visible text like a heading or <label>). This is generally preferred when a visible label exists.
aria-describedby – Provides an accessible description by referencing the ID of another element. Screen readers read this after the name, usually for instructions, hints, or error messages.
Think of it like this: aria-label writes a name directly, aria-labelledby points to an existing visible name, and aria-describedby adds extra explanation.
An icon button <button aria-label="Search"></button> – gives the button an accessible name since no text is visible.
A form input <input id="username" aria-labelledby="username-label"> with <label id="username-label">Username</label> – accessible name comes from the label.
The same input <input ... aria-describedby="username-hint"> with <p id="username-hint">Enter your email, not nickname</p> – accessible description provides extra context.
A modal dialog <div role="dialog" aria-labelledby="dialog-title" aria-describedby="dialog-desc"> – the title acts as the name, the description adds details.
Use visible text whenever possible; prefer aria-labelledby over aria-label if text exists on the page.
Use aria-label for elements without visible text (icon-only buttons, landmark regions).
Use aria-describedby for hints, help text, or error messages — not as the main label.
You can combine them: aria-labelledby for the name and aria-describedby for additional instructions.