Back to blog
Accessibility·November 2026·14 min read

ARIA labels for ecommerce: when to use them and when to avoid them

TL;DR

  • First rule of ARIA: do not use ARIA if native HTML already provides the semantics.
  • aria-label: only for elements with no visible text (icon buttons, SVG controls).
  • aria-labelledby: when the label text already exists on the page.
  • aria-describedby: for supplementary info (error messages, help text).
  • aria-live: essential for cart updates, filter counts, stock alerts.
  • Over-ARIAing is as harmful as under-ARIAing. More ARIA does not mean better accessibility.

ARIA (Accessible Rich Internet Applications) attributes improve web accessibility by communicating semantics to screen readers. They are also one of the most commonly misused tools in accessibility. Many ecommerce sites add ARIA to everything, believing more ARIA means better accessibility. The opposite is often true.

This guide covers when ARIA labels, roles and states are required on ecommerce stores, when they cause harm, and the specific code patterns for real ecommerce UIs.

What is ARIA and what is an ARIA label?

ARIA is a set of HTML attributes defined by the W3C that add accessibility information to elements. An ARIA label specifically refers to the aria-label attribute, which provides an accessible name for an element when no visible text label exists.

Screen readers use the accessible name to announce what an element is. When a screen reader encounters a button, it announces: “[accessible name], button.” If the button contains visible text, the text is the accessible name. If it contains only an icon, you need aria-label to provide the name.

<!-- Icon button: needs aria-label -->
<button aria-label="Search">
  <svg><!-- search icon --></svg>
</button>
<!-- Screen reader: "Search, button" -->

<!-- Text button: no aria-label needed -->
<button>Add to cart</button>
<!-- Screen reader: "Add to cart, button" -->

The first rule of ARIA

The W3C's first rule: do not use ARIA if a native HTML element or attribute already provides the semantics and behavior you need.

A native <button> is keyboard focusable, announces its role, responds to Enter and Space and communicates disabled state. A <div role="button"> requires manual keyboard handling and is more likely to have gaps.

Instead ofUseWhy
<div role="button"><button>Built-in keyboard + role
<div role="link"><a href>Navigable, right-click, open in new tab
<div role="checkbox"><input type="checkbox">Native checked state + Space toggle
<span role="img" aria-label><img alt>Native image semantics
<div role="navigation"><nav>Semantic landmark element

aria-label vs aria-labelledby vs aria-describedby

These three attributes serve different purposes. Confusing them is a common source of bugs.

AttributeProvidesSourceWhen to use
aria-labelAccessible nameString value in attributeNo visible text label exists
aria-labelledbyAccessible nameReferences another element's IDLabel text exists on page
aria-describedbyDescription (supplementary)References another element's IDExtra context (errors, help text)
<!-- aria-label: name from string -->
<button aria-label="Close cart">
  <svg><!-- X icon --></svg>
</button>

<!-- aria-labelledby: name from existing element -->
<h2 id="cart-heading">Your Cart</h2>
<dialog aria-labelledby="cart-heading">...</dialog>

<!-- aria-describedby: extra context -->
<input id="email" aria-describedby="email-error" />
<p id="email-error">Please enter a valid email address.</p>

The practical test: if removing the text would leave the user unable to identify the element, it is a label. If removing it would leave less context but the element is still identifiable, it is a description.

When aria-label overrides visible text

aria-label completely overrides the accessible name. If a button shows “Add to Cart” and has aria-label="Purchase this item", screen readers say “Purchase this item” while sighted users see “Add to Cart.”

Voice control users (Dragon NaturallySpeaking, iOS Voice Control) say what they see: “Click Add to Cart.” That command fails because the accessible name is different. This is a WCAG 2.5.3 Label in Name failure.

The rule: the accessible name must contain the visible label text. Valid: aria-label="Add Blue Wireless Headphones to Cart" when the button shows “Add to Cart.” Invalid: aria-label="Purchase this item"when the button shows “Add to Cart.”

ARIA for add-to-cart buttons

On collection pages with multiple products, a row of identical “Add to cart” buttons is unusable for screen reader users navigating by button list. Three solutions:

<!-- Option 1: aria-label with product name -->
<button aria-label="Add Blue Wireless Headphones to cart">
  Add to cart
</button>

<!-- Option 2: aria-describedby referencing product title -->
<h3 id="product-42">Blue Wireless Headphones</h3>
<button aria-describedby="product-42">Add to cart</button>

<!-- Option 3: visually hidden text -->
<button>
  Add to cart
  <span class="sr-only">Blue Wireless Headphones</span>
</button>

On a product page, “Add to cart” is sufficient since the page context makes the product clear. For variant products, ensure the selected variant is communicated before the button in the page flow.

ARIA for quantity selectors

The minus/number/plus quantity stepper is common in ecommerce:

<fieldset>
  <legend>Quantity</legend>
  <button aria-label="Decrease quantity">−</button>
  <input type="number" value="1" min="1"
         aria-label="Quantity" />
  <button aria-label="Increase quantity">+</button>
</fieldset>

The minus and plus buttons need aria-label since they contain only punctuation. Use type="number" for the input. Group with <fieldset> + <legend> or role="group" + aria-labelledby.

ARIA for product cards

Product cards typically have an image link and a title link both pointing to the same URL, creating duplicate tab stops:

<article>
  <!-- Image link hidden from tab order -->
  <a href="/product/42" aria-hidden="true" tabindex="-1">
    <img src="headphones.jpg" alt="" />
  </a>

  <!-- Title link is the primary tab target -->
  <h3><a href="/product/42">Blue Wireless Headphones</a></h3>

  <p>$79.99</p>

  <button aria-label="Add Blue Wireless Headphones to cart">
    Add to cart
  </button>
</article>

The image gets alt="" (decorative, since the title link provides the name) and the image link gets aria-hidden="true" + tabindex="-1" to remove the duplicate tab stop. The price must be inside the card's accessible content, not just visually positioned nearby.

ARIA for mega menus

Mega menus need ARIA to communicate open/closed state and panel relationships. See our keyboard navigation guide for the full keyboard interaction pattern.

<nav aria-label="Main navigation">
  <ul>
    <li>
      <button aria-expanded="false"
              aria-controls="women-panel">
        Women
      </button>
      <div id="women-panel" role="region"
           aria-label="Women categories" hidden>
        <!-- mega menu content -->
      </div>
    </li>
  </ul>
</nav>
  • aria-expanded toggles between true and false when the panel opens/closes
  • aria-controls points to the panel ID
  • The panel has role="region" and a label
  • Escape closes the panel and returns focus to the trigger button

ARIA for modal dialogs

Cart drawers, quick-view product dialogs, size guides, age verification and newsletter popups all use the same ARIA pattern:

<dialog role="dialog" aria-modal="true"
        aria-labelledby="cart-title">
  <h2 id="cart-title">Your Cart (3 items)</h2>
  <!-- cart contents -->
  <button aria-label="Close cart">✕</button>
</dialog>

Required JavaScript behaviors:

  • Move focus into the dialog on open (first focusable element or the heading with tabindex="-1")
  • Trap focus inside: Tab from last element cycles to first
  • Close on Escape key
  • Return focus to the trigger element on close
  • Mark background content as inert

The close button needs an accessible name. “Close cart” is better than just “Close” for context when navigating by button list.

ARIA live regions for cart updates

Live regions are one of the most important ARIA features for ecommerce and one of the most frequently missing. A live region is a DOM area that screen readers monitor and announce changes automatically.

<!-- Add this container to your page (empty initially) -->
<div id="cart-status" aria-live="polite"
     class="sr-only"></div>

<!-- When user adds to cart, update the text: -->
<script>
document.getElementById('cart-status').textContent =
  'Blue Wireless Headphones added to cart. 3 items total.';
</script>

Ecommerce uses for live regions:

  • Cart confirmations: “Product added to cart. 3 items in cart.”
  • Filter result counts: “24 products matching your filters.” See our accessible search and filters guide.
  • Stock alerts: “Only 2 left in stock.”
  • Price updates: “Price updated to $79.99 for Size M, Blue.”
  • Form errors: “Please enter a valid email address.” (use role="alert" for errors)

Two types: aria-live="polite" waits for the user to be idle before announcing. aria-live="assertive" (equivalent to role="alert") interrupts immediately. Use assertive only for critical errors. Everything else is polite.

Common mistakes: inserting content before the live region element exists in the DOM; using assertive for non-urgent updates; adding aria-live to focused elements (causes double announcement).

ARIA for search and filters

Ecommerce search and filter interfaces have specific ARIA needs:

<!-- Search with autocomplete -->
<input type="search" aria-label="Search products"
       role="combobox" aria-expanded="false"
       aria-autocomplete="list"
       aria-controls="search-results" />
<ul id="search-results" role="listbox" hidden>
  <li role="option">Blue Wireless Headphones</li>
</ul>

<!-- Filter group -->
<fieldset>
  <legend>Color</legend>
  <label><input type="checkbox" /> Blue (24)</label>
  <label><input type="checkbox" /> Red (18)</label>
</fieldset>

<!-- Result count live region -->
<p aria-live="polite">Showing 24 of 156 products</p>

For color swatches (visual-only selectors), each swatch needs an accessible name: aria-label="Blue"on the button or a visually hidden label. Without this, screen readers announce only “button” for each swatch.

ARIA for checkout forms

Checkout is the highest-risk page for accessibility violations. See our checkout accessibility guide for the full picture. Key ARIA patterns:

<!-- Required field -->
<label for="email">Email address</label>
<input id="email" type="email" required
       aria-required="true"
       autocomplete="email" />

<!-- Field with error -->
<label for="zip">ZIP code</label>
<input id="zip" aria-invalid="true"
       aria-describedby="zip-error" />
<p id="zip-error" role="alert">
  Please enter a valid ZIP code.
</p>

<!-- Multi-step progress -->
<nav aria-label="Checkout steps">
  <ol>
    <li aria-current="step">Shipping</li>
    <li>Payment</li>
    <li>Review</li>
  </ol>
</nav>
  • Use aria-required="true" in addition to the HTML required attribute for maximum screen reader support
  • Mark invalid fields with aria-invalid="true"
  • Link error messages with aria-describedby
  • Use autocomplete attributes for all address and payment fields (form accessibility guide)
  • Use aria-current="step" on multi-step checkout progress indicators

Over-ARIAing: common mistakes

MistakeProblemFix
role="button" on <button>Redundant, adds code noiseRemove the role attribute
aria-label on text paragraphOverrides visible textRemove aria-label
aria-hidden="true" on buttonHides entire button from screen readersOnly use on decorative child icons
role="presentation" on form inputRemoves input semanticsNever strip semantics from interactive elements
aria-label on every <li>Excessive verbosityLabel the list, not each item
role="list" on <ul>Redundant (Safari VoiceOver workaround)Usually unnecessary; test before adding
aria-live on focused elementsDouble announcementUse live region on separate container

Testing ARIA with screen readers

Automated tools (axe-core, Lighthouse) catch ARIA syntax errors: missing required attributes, invalid values, conflicting roles. They cannot catch semantic misuse or whether labels make sense in context. Manual testing is required.

Essential tests for ecommerce:

  • Button list review. NVDA: Insert+F7, select Buttons. Are all buttons listed with meaningful names? Do add-to-cart buttons include product names?
  • Form field review. Same dialog, select Form Fields. Do all inputs have labels? Are required fields announced as required?
  • Tab through checkout. Can you complete the entire flow without a mouse? Does focus move logically? See our screen reader testing guide.
  • Cart update announcement. Add a product. Does the screen reader announce the confirmation without navigating to the mini-cart?
  • Modal focus. Open a cart drawer. Does focus move in? Is it trapped? Does Escape close it? Does focus return to the trigger?
  • Filter announcement. Apply a filter. Does the result count update get announced?

Frequently asked questions

What is an ARIA label?
An ARIA label (aria-label) is an HTML attribute that provides an accessible name for an element when no visible text label exists. Screen readers read the aria-label value to announce what the element is.
When should you use aria-label on ecommerce sites?
Use it on interactive elements with no visible text: icon-only buttons (cart, search, close, wishlist), image links and SVG controls. Do not use it on elements that already have visible text.
What is the difference between aria-label, aria-labelledby and aria-describedby?
aria-label provides a name as a string. aria-labelledby references another element's text as the name. aria-describedby adds supplementary description. Use aria-labelledby when label text already exists on the page.
What is the first rule of ARIA?
Do not use ARIA if native HTML provides the semantics you need. A native <button> has built-in keyboard access and role. A <div role="button"> requires manual implementation.
What is over-ARIAing?
Adding unnecessary ARIA to elements already accessible via native HTML. Examples: role="button" on a <button>, aria-label on a paragraph with text. It creates noise and can override correct behavior.
How do you use aria-live for ecommerce cart updates?
Add a container with aria-live="polite". When a user adds to cart, update the container text (e.g., “Blue Headphones added. 3 items total.”). Screen readers announce the change automatically.
Does aria-label affect SEO?
aria-label does not directly affect rankings. However, correct ARIA improves WCAG compliance, which reduces ADA lawsuit risk and supports page experience signals.
How do you make modals accessible with ARIA?
Use role="dialog", aria-modal="true" and aria-labelledby pointing to the heading. Move focus in on open, trap focus, close on Escape, return focus to trigger on close.
What ARIA attributes do product cards need?
Hide duplicate image links with aria-hidden="true" and tabindex="-1". Add product-specific aria-label to add-to-cart buttons. Ensure price is programmatically associated with the product.
How do you test ARIA labels?
Use NVDA (free, Windows) or VoiceOver (Mac). Navigate by Tab for buttons/links. Use the elements list (NVDA: Insert+F7) to review all form fields and buttons. Test cart updates, modals and filters manually.

Complyko scans your ecommerce store for ARIA issues including missing labels, incorrect roles, duplicate tab stops and missing live regions. Get a free report with code-level fix suggestions.

Get your free scan →