/ โ† Accessibility Fixes / ARIA Labels
In this guide
  1. How a browser decides what a control is called
  2. The ARIA findings you are most likely to see
  3. The fix, step by step
  4. Correct patterns you can copy
  5. ARIA mistakes that make things worse
  6. Where ARIA problems come from
  7. Keeping accessible names correct
  8. Questions and answers

How a browser decides what a control is called

Browsers build an accessibility tree alongside the page, and each interactive element in it gets a role (button, link, textbox) and a name. WCAG 4.1.2, Name, Role, Value, at level A, requires that every user interface component has a name that assistive technology can read. The rules the browser follows are set out in the W3C's Accessible Name and Description Computation specification. In simplified form, the first of these that exists wins:

  1. aria-labelledby: the text of the element or elements whose IDs it lists.
  2. aria-label: the string in the attribute.
  3. Native labelling: a connected <label> for a form field, alt for an image, <caption> for a table, <legend> for a fieldset.
  4. Content: for buttons, links and some other roles, the text inside the element, including the alt of any image in it.
  5. title: a last resort, and a weak one.

Two consequences surprise people. First, ARIA overrides what is on screen: a button showing "Buy now" with aria-label="Add to cart" is announced as "Add to cart". Second, ARIA changes only what assistive technology is told. It does not add keyboard behaviour, focus or visible text. That is why the first rule of ARIA, as the W3C puts it, is to use a native HTML element with the semantics you need wherever one exists.

AttributeWhat it doesUse it for
aria-labelSets the name to a string you type.Controls with no visible text at all, such as an icon button.
aria-labelledbySets the name from other elements on the page, by ID.When visible text elsewhere already names the element, such as a dialog title or a section heading.
aria-describedbyAdds a description, read after the name and role.Hints, format instructions and error messages.
aria-hidden="true"Removes the element and its children from the accessibility tree.Decorative icons and duplicated content. Never on anything focusable.

The ARIA findings you are most likely to see

Button or link has no accessible name

The most common and most serious. A hamburger menu, a close cross, a social icon or a slider arrow built from an SVG or icon font, with no text inside. A screen reader says only "button", and a voice control user has nothing to say to press it.

<!-- Fails: nothing to announce -->
<button class="menu-toggle"><svg viewBox="0 0 24 24">...</svg></button>

<!-- Fixed -->
<button class="menu-toggle" aria-expanded="false" aria-controls="main-menu" aria-label="Menu">
  <svg aria-hidden="true" focusable="false" viewBox="0 0 24 24">...</svg>
</button>

Accessible name does not contain the visible label

WCAG 2.5.3, Label in Name, at level A, requires that when a control has visible text, its accessible name includes that text, ideally at the start. A voice control user looks at a button labelled "Send" and says "click Send". If the code says aria-label="Submit enquiry form", the command fails. The simplest fix is usually to delete the aria-label and let the visible text be the name.

aria-labelledby points at an ID that does not exist

The attribute takes one or more IDs separated by spaces. If an ID is misspelt, was changed in a redesign, or is duplicated on the page, the name comes out empty or wrong. Components rendered more than once, such as a product card or an accordion, are a frequent cause, because hard-coded IDs repeat.

aria-hidden element is focusable

If something is hidden from the accessibility tree but can still receive keyboard focus, a screen reader user tabs to it and hears silence or a confusing fragment. It often happens with off-screen menus, closed modals and carousel slides that are hidden with aria-hidden="true" but still contain links.

aria-label used where it is not supported

ARIA names are prohibited on generic elements. An aria-label on a plain <div>, <span> or <p> with no role is ignored by many screen readers, so the text never reaches the user. If the text matters, make it visible; if the element needs a name, it probably needs a proper role or element first.

The fix, step by step

Step 1

Read the computed name in developer tools

Run the Accessibility Audit and open the first flagged element in your browser. In Chrome or Edge, inspect it and open the Accessibility pane in the Elements panel, which shows the computed role and name and which source the name came from. Firefox has a similar Accessibility Inspector. Write down the current name for each flagged element. Seeing the name the browser actually computes is faster and more reliable than reading the markup and guessing.

Step 2

Name every icon-only control

For every button or link with no visible text, add a short name that says what it does, such as aria-label="Close", aria-label="Next slide" or aria-label="Search". Alternatively, put the words in a visually hidden span inside the element, which also survives automatic page translation more reliably. Hide the icon itself with aria-hidden="true" so it is not announced separately. Keep names short, and do not include the role, because the screen reader already says button or link.

Step 3

Replace aria-label that fights visible text

Search your templates for aria-label on elements that already show text: buttons, links, tabs and menu items. Where the label repeats the visible text, delete it. Where it says something different, either delete it and improve the visible text, or make sure the aria-label starts with the exact visible words, such as Read more about boiler servicing on a link showing Read more. This satisfies Label in Name and keeps voice control working.

Step 4

Repair broken aria-labelledby references

For every aria-labelledby and aria-describedby on the page, check that each ID it lists exists exactly once, with identical spelling and case. In the browser console, document.querySelectorAll('[aria-labelledby]') lets you loop through them quickly. In components that render many times, generate unique IDs per instance, for example with the useId hook in React or by adding the product or post ID. Then recheck the computed name in developer tools.

Step 5

Remove aria-hidden from anything focusable

Find elements with aria-hidden="true" that contain links, buttons, inputs or anything with a tabindex. If the content is truly hidden, such as a closed menu or modal, hide it with the hidden attribute, display: none or the inert attribute, all of which remove it from both the tab order and the accessibility tree. If the content is visible and usable, remove aria-hidden so screen reader users can reach what everyone else can.

Step 6

Take ARIA off elements that do not support it

Remove aria-label from plain divs, spans and paragraphs that have no role, and decide what the text was for. If it was extra information, make it visible or connect it with aria-describedby to a real control. If the element is clickable, replace it with a real <button> or <a href>, which brings keyboard support and a role for free. Also delete redundant roles, such as role="button" on a button element.

Step 7

Confirm the names with a screen reader

Open the page with NVDA and press Tab through every control, or use the VoiceOver rotor on a Mac to list form controls, links and landmarks. Each item should be announced with a clear name, the right role and any state, such as expanded or pressed. Listen for anything announced as just button or link, names that repeat, and hidden content that is still read. Then run the Accessibility Audit again and confirm the findings have cleared.

Correct patterns you can copy

A section named by its visible heading

<section aria-labelledby="delivery-heading">
  <h2 id="delivery-heading">Delivery and returns</h2>
  ...
</section>

A <section> only becomes a region landmark when it has a name, and reusing the heading keeps the name and the visible text in step.

Two navigation areas told apart

<nav aria-label="Main">...</nav>
<nav aria-label="Footer">...</nav>

Screen readers already say "navigation", so the label is just "Main" or "Footer", not "Main navigation".

A visually hidden name that translates

<a href="/basket" class="basket-link">
  <svg aria-hidden="true" focusable="false">...</svg>
  <span class="visually-hidden">Basket</span>
  <span class="count">2</span>
</a>
.visually-hidden {
  position: absolute; width: 1px; height: 1px;
  margin: -1px; padding: 0; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

Some automatic translation tools translate page text but not attribute values, so a visually hidden span is often a safer choice than aria-label on multilingual sites.

A dialog named by its title and described by its text

<div role="dialog" aria-modal="true" aria-labelledby="dlg-title" aria-describedby="dlg-desc">
  <h2 id="dlg-title">Remove item?</h2>
  <p id="dlg-desc">The blue kettle will be removed from your basket.</p>
  <button type="button">Remove</button>
  <button type="button">Keep it</button>
</div>

The native <dialog> element opened with showModal() is now well supported and handles focus containment for you; the labelling works the same way.

ARIA mistakes that make things worse

MistakeWhat the user experiencesFix
<div role="button" aria-label="Save"> with only a click handlerAnnounced as a button but cannot be reached or pressed with the keyboard.Use <button type="button">.
aria-label stuffed with keywordsLong, repetitive announcements that bury the real action.A short name saying what the control does.
aria-label on an input that has a visible labelThe visible label is ignored; voice commands may fail.Connect the <label> and remove aria-label.
Role words in the name, such as aria-label="Close button"Hears "Close button, button".aria-label="Close".
aria-hidden="true" on the body or main wrapper while a modal is openWorks only if the modal sits outside that wrapper; otherwise the whole page, modal included, goes silent.Use a native dialog or the inert attribute on background content.
Names added to every decorative iconNoise: "star, star, star, star, star, 4 stars".Hide decorative icons and name the group once.
โš ๏ธ Adding ARIA to silence a checker finding without testing the result is the quickest way to make a page less accessible. If you are not sure what an attribute does, removing it is often safer than adding more.

Where ARIA problems come from

WordPress. Menu toggles, search icons and social icon blocks in themes and page builders are the usual sources. Block themes generally output labelled navigation toggles; older themes and builder widgets may not. Many builders offer an "ARIA label" or "accessible name" field on icon and button widgets. Where they do not, a child theme template override is the durable fix.

Shopify. Themes provide most icon buttons, such as the cart, account and search icons in the header and the slider controls in product galleries. Their labels often come from the theme's translation strings in the locale files, so a missing label may be an empty translation rather than missing markup. Check apps that inject chat buttons, review stars and pop-ups too.

React, Vue and other frameworks. Component libraries usually label their own controls, but custom icon buttons are often written without a name. Make the name a required prop on your IconButton component, generate IDs with the framework's ID helper, and use the eslint-plugin-jsx-a11y rules, or the equivalent for your framework, to catch missing names and invalid ARIA while coding. For wider framework advice see the React and Next.js accessibility guide.

Keeping accessible names correct

  1. Prefer visible text. A button that says "Download brochure" needs no ARIA at all and helps every visitor.
  2. Build one icon button component that cannot be used without a name, and use it everywhere.
  3. Review aria-label values whenever visible text changes, so the two do not drift apart.
  4. Run automated checks in development and the Accessibility Audit after each release.
  5. Include a quick screen reader pass in testing for any new interactive component, such as a menu, tab set or modal.

ARIA naming overlaps with two other guides: form fields are covered in fixing form labels, and links whose visible text is vague are covered in fixing vague link text. Controls you cannot reach at all belong in fixing keyboard navigation.

Questions and answers

1. What is the difference between aria-label and aria-labelledby?

Both set an element's accessible name, but from different places. aria-label takes a string written directly in the attribute, so it is invisible on screen and must be kept up to date by hand. aria-labelledby takes the IDs of other elements and uses their visible text, so the name and what sighted users see stay in step automatically. When suitable visible text already exists on the page, aria-labelledby is usually the better choice. If both are present, aria-labelledby wins.

2. When should I use aria-describedby instead?

Use aria-describedby for extra information that supports the name rather than replacing it: a password rule, a date format, a character limit or an error message. Screen readers read the description after the name and role, often after a short pause, and some users turn descriptions off. So the essential purpose of the control belongs in the name, and the helpful detail belongs in the description. Like aria-labelledby, it takes one or more IDs of elements on the page.

3. Does aria-label help SEO?

It should not be relied on for SEO. aria-label is for assistive technology and is not visible text, so it is not a way to add keywords to a page. Search engines may read attribute values, but stuffing them with search terms makes the page worse to use with a screen reader and adds no meaningful value. If words matter for search, they belong in visible headings, text, links and alt text, where they help every visitor as well as search engines and AI tools.

4. Why does my checker say the button has no name when I added a title attribute?

The title attribute is the last fallback in the accessible name calculation and is not treated as a reliable label by many tools or assistive technologies. It is also only shown as a mouse hover tooltip, so keyboard and touch users never see it. Some checkers therefore still report the button. Give the button a proper name with visible text, a visually hidden span or aria-label, and remove the title unless it adds a genuinely useful extra hint for mouse users.

5. Is it wrong to use ARIA at all?

No. ARIA is essential for custom components that have no native HTML equivalent, such as tab sets, tree views and comboboxes, and for naming things like icon buttons and landmarks. The problem is ARIA used as a shortcut instead of the right HTML element, or added without testing. The W3C advice is to use native elements first, and when ARIA is needed, to follow the patterns in the ARIA Authoring Practices Guide and test them with real screen readers.

6. Can aria-labelledby point to hidden text?

Yes. aria-labelledby and aria-describedby include the text of the elements they reference even when those elements are hidden with the hidden attribute or display none. That lets you build a name from text that is not shown on screen. Use this carefully: hidden names cannot be checked by sighted testers, and they drift out of date more easily. Visible text or a visually hidden span inside the control is usually simpler to maintain and to review.

7. Should every section and div have an aria-label?

No. Adding names to ordinary content creates noise and can be ignored anyway, because names are not supported on generic elements. Name interactive controls, landmarks where there is more than one of the same type, such as two navigation areas, and sections you want to appear as landmarks. Headings already give screen reader users a way to move through content, so a well structured heading outline does more than a page full of aria-label attributes.

Find controls with missing or broken names

The Accessibility Audit tests your page against WCAG 2.2 level AA and lists each finding, such as buttons with no name and invalid or conflicting ARIA attributes, with the element that failed and the success criterion behind it.

Open Accessibility Fixes โ†’
๐Ÿ’ฌ Got a problem?
Related Guides: All Accessibility Fixes  ·  Fixing Form Labels  ·  Fixing Keyboard Navigation  ·  Fixing Missing or Wrong Alt Text  ·  Learning Hub

About aiwebpageseo

aiwebpageseo.com is a data-driven SEO and AEO (Answer Engine Optimisation) platform providing a free suite of technical SEO tools. Rather than relying on AI-theorised assumptions, the platform analyses live URL performance, delivering objective diagnostics, page speed metrics, CLS debugging, and site crawl data alongside actionable technical tutorials.