Who it affects
Someone who is blind, booking a GP appointment online tabs to a button and hears only 'button'. It could be Confirm, Cancel or Close, and pressing the wrong one loses the slot.
Someone using voice control says 'click close' and nothing happens, because the close button's name is empty.
Someone reading with a Braille display feels 'btn' with nothing after it and has to guess from whatever is around it.
Broken versus fixed
Both examples are live and rendered in a sandboxed frame. The broken one is deliberately broken.
A screen reader announces: button. Then: button. The person cannot tell the close button from the search button.
Announced: Close, button. Then: Search appointments, button.
Show the markup behind both examples
<style>body{font-family:system-ui;margin:0;padding:16px}.panel{border:1px solid #cfd6dd;border-radius:8px;padding:12px;max-width:360px}.row{display:flex;gap:8px;align-items:center;justify-content:space-between}button{border:1px solid #9aa5b1;background:#fff;border-radius:6px;width:36px;height:36px;cursor:pointer}svg{width:18px;height:18px;stroke:#1f2937;stroke-width:2;fill:none}</style>
<div class="panel">
<div class="row"><strong>Book an appointment</strong>
<button><svg viewBox="0 0 24 24"><path d="M6 6l12 12M18 6L6 18"/></svg></button></div>
<div class="row" style="margin-top:10px"><input type="text" aria-label="Search appointments" placeholder="GP name">
<button><svg viewBox="0 0 24 24"><circle cx="11" cy="11" r="7"/><path d="M16 16l5 5"/></svg></button></div>
</div>
<style>body{font-family:system-ui;margin:0;padding:16px}.panel{border:1px solid #cfd6dd;border-radius:8px;padding:12px;max-width:360px}.row{display:flex;gap:8px;align-items:center;justify-content:space-between}button{border:1px solid #9aa5b1;background:#fff;border-radius:6px;width:36px;height:36px;cursor:pointer}svg{width:18px;height:18px;stroke:#1f2937;stroke-width:2;fill:none}</style>
<div class="panel">
<div class="row"><strong>Book an appointment</strong>
<button aria-label="Close"><svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M6 6l12 12M18 6L6 18"/></svg></button></div>
<div class="row" style="margin-top:10px"><input type="text" aria-label="Search appointments" placeholder="GP name">
<button aria-label="Search appointments"><svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><circle cx="11" cy="11" r="7"/><path d="M16 16l5 5"/></svg></button></div>
</div>
Test it by hand in two minutes
- Press Tab to each button on the page. For every one that shows only an icon, right click it, choose Inspect, and look for text inside the button, an aria-label, or an img with alt.
- Start NVDA and press Insert+F7, then choose Buttons; or open VoiceOver's rotor with Ctrl+Option+U. Any button listed without a name fails.
- If you used aria-label on a button that also shows words, check the label contains those words, otherwise voice control users cannot say what they see.
- Shrink the browser until the mobile layout appears. The hamburger menu button that shows up there is the one most often missed.
The fix
<button class="close"><svg viewBox="0 0 24 24"><path d="M6 6l12 12M18 6L6 18"/></svg></button>
<button class="close" aria-label="Close"><svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M6 6l12 12M18 6L6 18"/></svg></button>
Name the action, not the picture: Close, not Cross. Mark the SVG aria-hidden so its paths are not read out as noise before the name.
Visually hidden text
<button class="menu"><span class="bars"></span></button>
<button class="menu"><span class="bars" aria-hidden="true"></span><span class="visually-hidden">Menu</span></button>
Hidden text is the most robust option: it is translated, it survives CSS failures, and it needs no ARIA.
Image inside the button
<button><img src="search.svg"></button>
<button><img src="search.svg" alt="Search appointments"></button>
The image's alt text becomes the button's name. Do not also add aria-label, or you will have two names to keep in step.
Icon font
<button><i class="fa fa-print"></i></button>
<button><i class="fa fa-print" aria-hidden="true"></i> Print</button>
Icon fonts are read as a stray private-use character by some screen readers. Hide the icon and show the word, or hide it and add hidden text.
Common mistakes
- Using the title attribute as the only name; it is unreliable and never shown on a touch screen.
- Setting aria-label to something different from the visible text, so voice control users cannot say what they see.
- Leaving the SVG exposed, so the screen reader reads 'graphic' or 'image' before, or instead of, the name.
- Naming the button after the icon ('magnifying glass') instead of the action ('Search').
- Hiding the label text with display:none, which hides it from screen readers as well.
WCAG criteria this rule maps to
axe-core tags this rule as WCAG 2.2 level A. It is one of the checks for:
- 4.1.2 Name, Role, Value (level A). Official W3C text.
The scanner can see a button whose text, aria-label, aria-labelledby, image alt and title all amount to nothing. It cannot judge whether the name describes the action, and it will not notice ten buttons on one page all called 'Edit'. Automated tools find only part of the accessibility problems on a page; a pass on this rule is not a pass on the criterion.
Related rules
link-name
Every link needs text that a screen reader can announce and a voice control user can say.
A
Input buttons must have discernible text
input-button-name
An input element with type="submit", type="button" or type="reset" draws a button whose text comes from its value attribute.
A
ARIA buttons, links and menu items need a name
aria-command-name
When you give an element role="button", role="link" or role="menuitem", you are promising assistive technology that it is a control.
A
The words on a control must be part of its accessible name
label-content-name-mismatch
People who use voice control activate a control by saying the words they can see on it.