Skip to content

Buttons need a name

  • Rule: axe/button-name
  • Checks: Buttons must have discernible text
  • WCAG: 4.1.2
  • Fix class: content: A fix needs authored text.
  • People who use a screen reader or a braille display, most of them blind.
  • People who control the page by speaking.

Name the button for its action with aria-label, and hide the icon from assistive technology with aria-hidden="true".

<button type="button" aria-label="Close">
<svg aria-hidden="true" focusable="false"><use href="#icon-close"></use></svg>
</button>

Give the image an alt that names the button’s action. The button takes its name from the image’s text alternative.

<button type="button"><img src="search.svg" alt="Search"></button>

The button holds its text in a hidden element or draws it with CSS

Section titled “The button holds its text in a hidden element or draws it with CSS”

Put the words inside the button as text. To hide them visually, use a class that clips them but keeps them in the accessibility tree; display: none and visibility: hidden remove them from it. axe ignores text drawn with CSS content, and assistive technology does not announce it reliably.

<button type="button">
<svg aria-hidden="true" focusable="false"><use href="#icon-trash"></use></svg>
<span class="visually-hidden">Delete order</span>
</button>

Visible text elsewhere on the page already names the action

Section titled “Visible text elsewhere on the page already names the action”

Point aria-labelledby at that text by its id, so the name and the visible words stay the same.

axe accepts it and screen readers announce it, but it shows only while a mouse hovers, so keyboard, touch and voice control users never see the name.

Naming the icon rather than the action, such as aria-label="X" or aria-label="Magnifying glass"

Section titled “Naming the icon rather than the action, such as aria-label="X" or aria-label="Magnifying glass"”

People hear what the button looks like, not what it does. Name the action: “Close”, “Search”.

It takes the button out of the rule by hiding it from assistive technology, but the button stays focusable, so keyboard and screen reader users still reach a control nothing announces. axe then reports it under aria-hidden-focus.

The part of the fix that differs in React, in its syntax. The rest of the guidance holds.

An icon button component does not pass aria-label to its <button>

Section titled “An icon button component does not pass aria-label to its <button>”

Take the name as a required prop and set it on the <button> after spreading the other props, so nothing in the spread can replace it.

function IconButton({ icon: Icon, label, ...rest }) {
return (
<button type="button" {...rest} aria-label={label}>
<Icon aria-hidden="true" focusable="false" />
</button>
);
}

Passing aria-label to a component that does not forward it

Section titled “Passing aria-label to a component that does not forward it”

The prop never reaches the DOM, so the button stays unnamed. Check the rendered HTML, not the JSX.

axe-core’s documentation of the rule

CORA’s fix guidance adapts content from accessibility-agents, under the MIT License: see its notice.