🚀 LEVEL UP TO SENIOR:Unlock 500+ Advanced Practical Challenges & Exercises.
🎓 COURSERA PARTNER:Earn professional Google, Meta, and IBM certificates to supercharge your resume.
HTML MASTER CLASS /// LEARN TAGS /// BUILD STRUCTURE /// SEMANTIC WEB /// HTML MASTER CLASS /// LEARN TAGS ///

ARIA Labels: Precise Control Over What Gets Announced

Learn the distinct purpose of each ARIA labelling attribute, when to prefer one over another, and how they combine to fully describe a complex control.

Total XP: 0|💻 html XP: 0

Skill Matrix

UNLOCK NODES BY LEARNING NEW TAGS.

ARIA Labelling

Naming vs describing controls.


🚀 LEVEL UP TO SENIOR:Unlock 500+ Advanced Practical Challenges & Exercises.
🎓 COURSERA PARTNER:Earn professional Google, Meta, and IBM certificates to supercharge your resume.

aria-label, aria-labelledby, and aria-describedby give developers fine-grained control over accessible names and descriptions when native labelling markup isn't enough on its own.

1aria-label For Standalone Naming

aria-label sets the accessible name directly as a string on the element it's applied to, without needing any visible text to reference. It's most valuable on icon-only controls — a magnifying-glass search button, a hamburger menu toggle, a trash-can delete icon — where adding visible text would clutter the design but omitting a name entirely leaves screen reader users with nothing.

Because aria-label overrides any visible text content in the accessible name computation, using it on an element that already has clear visible text is a common source of the exact 'text mismatch' bug covered in the previous lesson — don't add it redundantly.

<button aria-label="Search">
  <svg aria-hidden="true">...</svg>
</button>
localhost:3000
✓ Announced: "Search, button"aria-hidden hides the decorative icon from the accessibility tree; aria-label supplies the name.

2aria-labelledby For Reusing Existing Text

When a suitable label already exists visibly on the page — most often a heading — aria-labelledby lets you reference it by id instead of duplicating the text into an aria-label. This keeps the accessible name automatically synchronized: if the heading text changes, the accessible name changes with it, with zero risk of drift.

aria-labelledby also uniquely supports referencing multiple ids, space-separated, letting you compose a name from several text fragments — commonly used to combine a category label with an item name in data tables or card grids.

<span id="lbl1">Billing</span> <span id="lbl2">Address</span>
<input aria-labelledby="lbl1 lbl2">
localhost:3000
✓ Composed Name: "Billing Address"aria-labelledby concatenated two separate text nodes into one accessible name, in order.

3aria-describedby For Hints And Errors

aria-describedby is announced after the accessible name and role, as supplementary description — never as a replacement for the name itself. It's the standard mechanism for connecting format hints ('Minimum 8 characters'), helper text, and, critically, live validation error messages to the field they describe.

A frequent real-world pattern combines aria-describedby with aria-invalid: when a field fails validation, aria-invalid="true" is set and aria-describedby points at the newly-rendered error message, so a screen reader user hears both that the field is invalid and exactly why in a single focus event.

<input aria-invalid="true" aria-describedby="email-err">
<p id="email-err">Enter a valid email address</p>
localhost:3000
✓ Announced: "Invalid, Enter a valid email address"Combining aria-invalid and aria-describedby delivers both the error state and its explanation in one pass.

4Step-by-Step Breakdown

Naming What Has No Visible Text. Not every control has visible text to derive a name from — icon-only buttons, unlabeled inputs, and complex widgets often need an explicit label. ARIA gives you three related but distinct tools: aria-label, aria-labelledby, and aria-describedby, each with a different job.

aria-label: An Inline Text Alternative. aria-label supplies an accessible name directly as a string, with no visible on-screen text required. It's the right tool exactly when there is no existing visible label to reference — most commonly icon-only buttons.

aria-label Use Case. An icon-only trash button has no visible text. Which attribute directly supplies its accessible name?

  • The title attribute exclusively
  • aria-label
  • alt, since it works on any element

aria-labelledby: Point At Existing Text. aria-labelledby references the id of another element and uses its text content as the accessible name — useful when a suitable label already exists elsewhere on the page, like a heading that should also name a related region.

aria-labelledby vs aria-label. When is aria-labelledby preferable to aria-label?

  • Always — it's a strict upgrade over aria-label
  • When suitable, already-visible text exists elsewhere to reuse
  • Never; aria-labelledby is deprecated

aria-describedby: Supplementary, Not Primary. aria-describedby adds a secondary description announced after the accessible name, typically used for hints, format requirements, or error messages — it never replaces the name itself, only supplements it.

aria-describedby Purpose. A password field has a visible hint 'Minimum 8 characters' below it. What's the correct way to connect it for screen reader users?

  • aria-describedby, pointing at the hint's id
  • aria-labelledby, replacing the primary label
  • Rely on the placeholder attribute alone

Labelling Toolkit Complete. You can now choose correctly between aria-label for standalone naming, aria-labelledby for reusing existing text, and aria-describedby for supplementary hints — the toolkit behind nearly every properly-labeled custom control.

Label An Icon-Only Button. A button with only an icon needs an aria-label so screen readers can announce its purpose.

Level Up 🚀

Advanced cheat sheets, SEO tricks, and interview prep for this topic.

Browser Support

ChromeSupported

Fully supported.

FirefoxSupported

Fully supported.

SafariSupported

Fully supported.

EdgeSupported

Fully supported.

Accessibility (A11y)

1aria-label Overrides Visible Text — Use It Deliberately

Because aria-label wins in the accessible name computation, applying it to an element that already has clear visible text risks silently hiding that text from screen reader users.

2aria-describedby Composes With Validation States For Complete Error Messaging

Pairing aria-invalid="true" with aria-describedby pointing at an error message delivers the field's invalid state and the reason in a single, efficient announcement.

SEO Implications

  • 1

    aria-label Text Is Not Indexed The Way Visible Text Is

    Search engines weight visible, crawlable text far more heavily than aria-label strings, so aria-label should never be used as a substitute for real visible copy intended for SEO.

  • 2

    Reused, Synchronized Labels Via aria-labelledby Reduce Content Drift Risk

    Because aria-labelledby always reflects current visible text, it avoids the SEO-irrelevant but UX-relevant risk of stale, duplicated label strings appearing out of sync with the page.

Best Practices

Prefer aria-labelledby Over aria-label When Visible Text Already Exists

It keeps the accessible name automatically synchronized with visible content, eliminating an entire category of label-drift bugs that plague duplicated aria-label strings.

Always Pair aria-invalid With aria-describedby On Validation Errors

Announcing only 'invalid' without the reason forces users to hunt for the error manually; combining both delivers a complete, actionable message in one announcement.

Frequent Bugs

THE BUG

A search button visibly says 'Search' but the screen reader announces just 'Go'.

THE FIX

A leftover aria-label="Go" is overriding the current visible text. Remove the aria-label or update it to match.

THE BUG

A form shows a red error message visually, but screen reader users tab past the field with no indication anything is wrong.

THE FIX

The error message isn't connected via aria-describedby, and aria-invalid isn't set. Wire both attributes to the rendered error element.

Real-World Examples

Composed Table Cell Label

A data table where each cell's accessible name combines its row and column headers using aria-labelledby.

<th id="col-status">Status</th>
<tr>
  <th id="row-1">Invoice #1042</th>
  <td aria-labelledby="row-1 col-status">Paid</td>
</tr>

Interview Prep

?Frequently Asked Questions

Pascual Vila

Pascual Vila

Frontend Instructor // Code Syllabus

Common Pitfalls & Errors

The Error //

Adding aria-label that duplicates and then diverges from visible text

<!-- Risky --> <button aria-label="Submit order">Submit</button> <!-- Safer: let visible text be the name --> <button>Submit order</button>

The Solution //

Prefer aria-labelledby to reference existing visible text automatically instead of hand-duplicating it into aria-label.

The Error //

Using aria-describedby without also setting aria-invalid on errors

<input aria-invalid="true" aria-describedby="err"> <p id="err">Required field</p>

The Solution //

The description alone doesn't communicate error state; pair it with aria-invalid="true" so users know something is wrong before hearing why.

Lesson Glossary

[01]aria-label

Sets an accessible name directly as a string.

Code Preview
aria-label="Close"

[02]aria-labelledby

Sets an accessible name by referencing another element's id.

Code Preview
aria-labelledby="id"

[03]aria-describedby

Adds a supplementary description after the name.

Code Preview
aria-describedby="hint"

[04]aria-invalid

Marks a form field as failing validation.

Code Preview
aria-invalid="true"

Continue Learning