If a screen reader user lands on a button on your site and only hears the word “button,” you have a button-name violation. That single missing string is enough to abandon a checkout, a sign-up, or a navigation menu.
1. What is the button-name violation?
axe-core's button-name rule fires when a <button> (or any element with role="button") has no accessible name. It is a direct violation of WCAG 2.1 4.1.2 Name, Role, Value (Level A) — meaning even the lowest tier of conformance is broken.
The "accessible name" is the string a screen reader (NVDA, JAWS, VoiceOver, TalkBack) reads when the button receives focus. Without one, the device just announces "button" — and that's all.
2. Why it matters
It's not just blind users. Anyone using voice control (Apple Voice Control, Dragon NaturallySpeaking, Android Voice Access) needs that name to issue a command. To say "click the Add to cart button," the system must recognize it as "Add to cart."
Scale: across recently crawled sites, Keysonar found over 22,000 button nodes failing this rule — meaning hundreds of users per site are excluded from primary interactions. It is consistently one of the top three violations in any large-scale accessibility audit.
3. When does it fire?
Five patterns we see repeatedly in production crawls:
- Empty button: No content at all.
- Icon only: SVG, FontAwesome, or a CSS background icon — no readable text.
- Image only: An
<img>child with no alt. - All text hidden by
aria-hidden: Removed from the accessibility tree. - Text hidden by
display:none: Hidden from both the screen and the reader.
4. The fixes
4.1 Icon buttons
The most common offender on e-commerce: cart, search, heart, share. Often there is no text besides the icon, so the button is announced as just "button."
<button class="cart-btn">
<svg viewBox="0 0 24 24">...</svg>
</button><button class="cart-btn" aria-label="Add to cart">
<svg aria-hidden="true" viewBox="0 0 24 24">...</svg>
</button>4.2 Modal close button (×)
<button onclick="close()">
<span aria-hidden="true">×</span>
</button><button onclick="close()" type="button">
<span aria-hidden="true">×</span>
<span class="sr-only">Close</span>
</button>
<style>
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
</style>4.3 Image button
<button>
<img src="/icons/search.svg">
</button><button>
<img src="/icons/search.svg" alt="Search">
</button>4.4 React / Next.js components
<button onClick={addToWishlist}>
<Heart className="w-5 h-5" />
</button><button
onClick={addToWishlist}
aria-label={t("product.addToWishlist")}
>
<Heart aria-hidden className="w-5 h-5" />
</button>On a multi-language site, source the label from the translation dictionary. An English aria-label on a Turkish page will be read by an English speech engine and become unintelligible to Turkish-speaking users.
5. How the accessible name is computed
The browser walks this priority list and uses the first non-empty result:
aria-labelledby(references the text content of another element)aria-label- The button's own text content (text, img alt, etc.)
titleattribute (least reliable — avoid)
<button aria-label="Confirm">
Add to cart
</button><button>Add to cart</button>6. Cases that get missed
- Late-rendered SPA buttons: Buttons inside modals or tabs that mount on user interaction. Static scanners may miss them — your crawler should hit them after the click that reveals them.
- Symbol text (×, +, →): A character like
×may be read as "multiplication sign" or skipped entirely. Symbols are not semantics. Always pair with sr-only text ("Close"). - title attribute: Invisible on touch devices and inconsistent across screen readers. Do not rely on it as a name source.
- Icon library defaults: FontAwesome, Material Icons, Heroicons — none of them set an aria-label automatically. Each consuming button must provide its own.
7. How to test
- axe DevTools browser extension: instant per-page scan. Best for fast developer feedback during build.
- Keysonar SEO Tools: site-wide automated scan, list of affected pages, regression tracking over time. No DevTools required.
- NVDA (Windows) / VoiceOver (macOS): manual screen-reader test for real-user feel. Tab through every button, write down what you hear.
- Lighthouse: Chrome DevTools accessibility audit — shorter report, CI-friendly.
8. Quick checklist
- Every <button> has visible text, an aria-label, or aria-labelledby.
- Icon-only buttons have an aria-label in the same language as the page.
- Buttons containing <img> have a non-empty alt or a parent aria-label.
- Symbol-only content (×, +) is paired with sr-only descriptive text.
- No redundant aria-label on buttons that already have visible text.
- Decorative icons inside buttons have aria-hidden="true".
- Late-mounted buttons (modals, dropdowns) are tested too.
- title attribute is NOT used as the accessible name source.
9. References
- WCAG 2.1 SC 4.1.2 — Name, Role, Value (Level A)
- WAI-ARIA Authoring Practices: Button pattern
- HTML Living Standard — The button element
- Accessible Name and Description Computation 1.2 (W3C)