button
Marks an element as a button — a control that triggers an action when activated. Use the native HTML <button> element first; only reach for role="button" on a <div> or <span> when there is no way to use the native element.
When to use
Almost never — use the native <button> element. The native element handles focus, the space and enter key activations, the disabled state, and form-submission semantics for free. Reaching for role="button" on a <div> means you have to reimplement all of that, and most authors don’t.
The legitimate cases for role="button" are narrow:
- You’re constrained by a third-party design system that ships non-button components.
- You’re authoring inside an environment where
<button>is unavailable (some legacy CMS templates). - You’re upgrading a
<div>for accessibility in the short term while planning a refactor.
If you do use role="button", you must also:
- Make the element focusable with
tabindex="0". - Wire up
keydownfor bothEnterandSpace(withevent.preventDefault()on Space to stop the page scrolling). - Manage the disabled state yourself via
aria-disabled="true"and prevent click handlers from firing.
Toggle buttons
If the button is a toggle (mute / unmute, play / pause, follow / unfollow), set aria-pressed to "true" or "false". Screen readers announce the state along with the label: “Mute, toggle button, not pressed”.
Common failures
<div onclick="…">Submit</div>— not focusable, not keyboard-operable, no role. Mouse users can use it; nobody else can.<a href="#" onclick="…">masquerading as a button. The browser treats it as a link, the SR announces it as a link, the user expects navigation.role="button"withouttabindex="0"— the screen reader announces “button” but the keyboard cannot reach it.- Custom buttons that respond to Enter but not Space.
- Buttons with no accessible name — icon-only buttons missing
aria-labelare the single most common failure axe-core catches.
Example
<!-- Preferred -->
<button type="button" aria-pressed="false">Mute</button>
<!-- Only when <button> is impossible -->
<div
role="button"
tabindex="0"
aria-pressed="false"
onclick="toggleMute()"
onkeydown="if (event.key === 'Enter' || event.key === ' ') { event.preventDefault(); toggleMute(); }"
>
Mute
</div>