Video examples

iOS Voiceover Safari

Android Talkback Chrome

Windows Jaws Chrome

Windows NVDA Chrome

Code examples

Use semantic HTML

This semantic HTML contains all accessibility features by default.

<button>
  Continue
</button>

Focusable disabled button

The preferred method is to use aria-disabled="true" so screen reader users can find the button, click submit and be notified of errors in the form.

<button aria-disabled="true">
  Continue
</button>

Fully disabled button

A button that uses the disabled attribute will not be focusable, but it is still discoverable by the screen reader while browsing.

<button disabled>
  Continue
</button>

When you can’t use semantic HTML

This custom button requires extra attributes and JS event listeners. Adding tabindex="0" makes it focusable.

<div role="button" tabindex="0">
  Continue
</div>

When there is no inner text

As a last resort, aria-label can be used.

<div role="button" tabindex="0" aria-label="Continue">
  <!-- icon -->
</div>

Developer notes

Name

  • Inner text should describe the purpose of the button.
  • aria-label="Button purpose" can also be used (as a last resort)

Role

  • Native button identifies as button by default
  • Use role="button" for custom elements

Group

  • Use aria-haspopup="true" for menu, listbox or modal
  • aria-controls="popupId" is not well supported

State

  • Toggle buttons aria-pressed="true/false"
  • Menus or expanders use aria-expanded="true/false"
  • Use the disabled state for inactive buttons
  • Use aria-disabled="true/false" state for inactive custom elements

Focus

  • Focus must be visible
  • Custom elements need tabindex="0" to be focusable