DEV Community

FrozonFreak
FrozonFreak

Posted on Originally published at thewebhig.hashnode.dev

Every control needs an accessible name (Web HIG tip #5)

An icon button looks obvious to anyone who can see the icon. A screen reader user hears "button" and has to guess what it does.

Web HIG tip #5 (Quick #69, HIG-A11Y-004): Every control needs an accessible name. Icon-only buttons are where this breaks most often.

Why it matters

Icon-only controls are everywhere: delete, edit, close, menu, share. Without a name:

  • Screen readers announce just "button", so a row of five icons sounds like five identical buttons
  • Voice control users can't say "click Delete" when the button has no name to match
  • The same trash icon can mean "delete this invoice" or "clear the whole list", and the icon alone doesn't tell you which
  • Automated accessibility checkers flag buttons and links with no name, so this also shows up in audits

The rule of thumb

Ask: if the icon disappeared, would this control still say what it does?

If not, give it a name.

<!-- Don't: no text, no aria-label, no <title> in the svg, so a screen reader just says "button" -->
<button><svg>…</svg></button>

<!-- Do: name the button, hide the decorative icon -->
<button aria-label="Delete invoice">
  <svg aria-hidden="true">…</svg>
</button>
Enter fullscreen mode Exit fullscreen mode

If the button already has visible text, like <button><svg aria-hidden="true">…</svg> Delete</button>, the text is the name. Don't add an aria-label to the icon or the button as well. If you ever do label a button that has visible text, the label must contain that text, so voice users can say what they see.

Do this instead

  • Name the action and its target, like "Delete invoice", not just "Delete" or "Trash"
  • Put the name on the <button> or link itself (an aria-label or visually hidden text), and mark the icon aria-hidden="true"
  • Use a real <button>, not a clickable <div> or <span>. A name on a <div> doesn't make it a button (see tip #3)
  • Add a visible tooltip or text label when the icon isn't widely understood. The accessible name helps assistive tech, not everyone

Quick check for your app

Tab through one screen with a screen reader on. Every control should be announced with a name that tells you what it does, and no icon button should come through as just "button". In browser dev tools, the Accessibility panel shows each control's computed name, so any empty one is a fix.


The Web HIG is a behavioral contract for how the web should behave, not a component library. Design systems define how it looks. The Web HIG defines how it behaves.

Top comments (2)

Collapse
 
svgicons profile image
Svg/icons •

A useful design-system rule is making reusable icon components decorative by default, while the button owns the accessible name. It keeps semantics out of the SVG asset.

Collapse
 
frozonfreak profile image
FrozonFreak •

Thanks, that's a great way to put it. Make the icon component decorative by default (aria-hidden="true"), and the button or link that uses it owns the name. That keeps the name next to the action it describes, so the same trash icon can be "Delete invoice" in one place and "Remove filter" in another. The one exception is a standalone icon that carries meaning on its own, like a status icon with no text next to it. For those, an explicit opt-in such as a label prop can give it a name.