When to use aria-label.
Native HTML first.
The first rule of ARIA is simple: don't use ARIA if native HTML can do the job. aria-label is powerful but frequently misused — added to elements that already have visible text, overriding the label users see, breaking voice control in the process. This page covers when it's appropriate (rarely), when it's wrong (often), and the alternatives that solve the same problem without ARIA.
Short answer: Use aria-label only when an element has no visible text — icon-only buttons, icon-only links, landmark regions without headings. Never use it when visible text exists; it overrides the label and breaks voice control. For inputs with visible labels, use <label for>. For the rest — leave it alone. No ARIA is better than bad ARIA.
✅ When aria-label is appropriate
Three cases. All involve missing visible text.
Icon-only buttons
<button aria-label="Search"><svg>...</svg></button> — the icon has no text. The aria-label is the only accessible name.
Icon-only links
<a href="/" aria-label="Home"><svg>...</svg></a> — no visible text. Without aria-label, screen readers announce the URL.
Multiple landmarks
<nav aria-label="Main"> and <nav aria-label="Footer"> — distinguish two navs. Screen readers announce "Main navigation" vs "Footer navigation".
Custom widgets
A complex custom control with no visible text needs an accessible name. Rare — most widgets have text.
✅ Before and after
Correct and incorrect uses.
<!-- ❌ aria-label overrides visible text --> <button aria-label="Submit the form">Submit</button> <!-- ❌ aria-label duplicates the label --> <label for="email">Email</label> <input id="email" type="email" aria-label="Email"> <!-- ❌ aria-label with no matching visible text --> <a href="/search" aria-label="Find items">Search</a>
❌ Button: screen reader says "Submit the form", voice control user says "click Submit" — no match. ❌ Input: aria-label overrides label for. The visible "Email" is ignored by the screen reader. ❌ Link: aria-label "Find items" overrides "Search". Voice control says "click Search" — no match. Rule: WCAG 2.5.3 — visible text must be contained in the accessible name.
<!-- ✅ Icon-only button --> <button aria-label="Search"> <svg>...</svg> </button> <!-- ✅ Icon-only link --> <a href="/" aria-label="Home"> <svg>...</svg> </a> <!-- ✅ Two nav landmarks --> <nav aria-label="Main menu">...</nav> <nav aria-label="Footer links">...</nav> <!-- ✅ Button with visible text — no aria-label needed --> <button>Submit</button> <!-- ✅ Input with visible label — no aria-label needed --> <label for="email">Email</label> <input id="email" type="email">
✅ Icon buttons: no visible text, aria-label is the only accessible name. Screen reader says "Search, button". ✅ Two navs: "Main menu navigation" vs "Footer links navigation" — screen reader users can distinguish them. ✅ Buttons with text: visible text IS the accessible name. No aria-label needed. ✅ Inputs with label for: the label element is the accessible name. No aria-label needed. Rule: aria-label only when no visible text exists.
Don't add aria-label to elements that already have text. This is the most common ARIA mistake and one of the most damaging. It overrides the visible label in the accessibility tree, so screen reader users hear one thing while sighted users see another. Voice control users break because the accessible name no longer contains the visible text. WCAG 2.5.3 (Label in Name) explicitly forbids this. If the element has visible text, the text is the label. Leave ARIA alone.
⚠️ Common mistakes
The aria-label mistakes that cost real time.
Overrides the visible text. Fix: remove it. The text is already the label.
aria-label wins; label for is ignored. Fix: use only one — label for is preferred.
Redundant — and can drift out of sync. Fix: remove aria-label.
Nothing visible — sighted users see an empty button. Fix: also add a visible icon or text.
The role is already announced. Fix: aria-label should describe the action, not the role.
Divs have no role. Fix: use a semantic element first.
Screen reader announces "button" with no name. Fix: add aria-label describing the action.
That's not what it's for. Fix: use aria-hidden="true" or CSS sr-only if you need to hide.
❓ Frequently asked
What is aria-label?
aria-label is an attribute that provides an accessible name for an element when no visible text is available. Screen readers announce it as the element's label. Use it when the element has no text — an icon-only button, a link with just an icon, a landmark region with no heading. If the element already has visible text, aria-label overrides it, which is often not what you want. The first rule of ARIA: use native HTML first, and add aria-label only when no native solution exists.
When should I use aria-label?
Three cases. (1) Icon-only buttons: button with an SVG icon and no text needs aria-label='Search' or aria-label='Menu'. (2) Icon-only links: a with just an SVG icon needs aria-label='Home' or the destination. (3) Landmark regions without a heading: nav needs aria-label to distinguish multiple navs. Never use aria-label when a visible label exists — it overrides the label, and screen reader users see nothing while blind users hear only the aria-label.
What is the difference between aria-label and label for?
label for is native HTML — it associates a visible label element with an input, both announcing the label to screen readers and making the label clickable. aria-label is invisible text only for screen readers. Use label for whenever a visible label exists or can exist. Use aria-label only when no visible label is possible — like an icon-only search button. If the input has a visible label, use label for. If it has no label and can't have one, use aria-label.
Why is aria-label bad for links?
If the link has visible text, aria-label overrides it — voice control users (who say 'click Search') can no longer click the link because the accessible name doesn't match the visible text. WCAG 2.5.3 (Label in Name) requires that the visible text be contained in the accessible name. If you add aria-label='Search page' to a link that says 'Search', voice control users are broken. Only use aria-label on links when the link has no visible text.
Can aria-label and visible text both be announced?
No. aria-label overrides visible text in the accessibility tree. Screen readers announce only the aria-label, not the visible text. This is why the rule is strict: don't add aria-label when the element has visible text, because you're removing the visible label from the screen reader output. If you want both, use aria-labelledby pointing to the visible element's id, or rely on visible text alone with no aria-label.
What is aria-labelledby vs aria-label?
aria-label takes a string directly: aria-label='Close'. aria-labelledby takes one or more ids and concatenates their text content: aria-labelledby='dialog-title close-text'. Use aria-label for short, self-contained strings. Use aria-labelledby when the label text is already in the DOM — it reuses visible text and stays in sync when the text changes. aria-labelledby is more flexible and less likely to go out of sync.