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>
When there are repeating buttons
Sometimes the design will call for multiple buttons with the same text label. In a case like this, aria-label
can be used to name each control’s purpose.
<button aria-label="Edit payment date">
Edit
</div>
<button aria-label="Edit payment amount">
Edit
</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