ARIA: button role
- Description
- All descendants are presentational
- Associated ARIA roles, states, and properties
- Basic buttons
- Toggle buttons
- Keyboard interactions
- Required JavaScript Features
- Required event handlers
- Examples
- Basic button example
- HTML
- CSS
- JavaScript
- Toggle button example
- HTML
- CSS
- JavaScript
- Result
- Accessibility concerns
- Best practices
- Specifications
- See also
Description
<div id="saveChanges" tabindex="0" role="button" aria-pressed="false">Save</div>
The above example creates a focusable button, but requires JavaScript and CSS to include button appearance and functionality. These are features provided by default when using the button and input with type="button" elements:
<button type="button" id="saveChanges">Save</button>
NOTE: If using
role="button"instead of the semantic<button>or<input type="button">elements, you will need to make the element focusable and define event handlers for click and keydown events. This includes handling the Enter and Space key presses in order to process all forms of user input. See the official WAI-ARIA example code.
In addition to the ordinary button widget, role="button" should be included when creating a toggle button or menu button using a non-button element.
All descendants are presentational
There are some types of user interface components that, when represented in a platform accessibility API, can only contain text. Accessibility APIs do not have a way of representing semantic elements contained in a button. To deal with this limitation, browsers automatically apply role presentation to all descendant elements of any button element as it is a role that does not support semantic children.
For example, consider the following button element, which contains a heading.
<div role="button"><h3>Title of my button</h3></div>
Because descendants of button are presentational, the following code is equivalent:
<div role="button"><h3 role="presentation">Title of my button</h3></div>
From the assistive technology user's perspective, the heading does not exist since the previous code snippets are equivalent to the following in the accessibility tree:
<div role="button">Title of my button</div>
Associated ARIA roles, states, and properties
aria-pressed- : The
aria-pressedattribute defines the button as a toggle button. The value describes the state of the button. The values includearia-pressed="false"when a button is not currently pressed,aria-pressed="true"to indicate a button is currently pressed, andaria-pressed="mixed"if the button is considered to be partially pressed. If the attribute is omitted or set to its default value ofaria-pressed="undefined", the element does not support being pressed.
- : The
aria-expanded- : If the button controls a grouping of other elements, the
aria-expandedstate indicates whether the controlled grouping is currently expanded or collapsed. If the button hasaria-expanded="false"set, the grouping is not currently expanded. If the button hasaria-expanded="true"set, it is currently expanded; if the button hasaria-expanded="undefined"set or the attribute is omitted, it is not expandable.
- : If the button controls a grouping of other elements, the
Basic buttons
Toggle buttons
- If
aria-pressedis not used, or is set to the "undefined" state, the button is not a toggle button. - If
aria-pressed="false"is used the button is a toggle button that is currently not pressed. - If
aria-pressed="true"is used the button is a toggle button that is currently pressed. - if
aria-pressed="mixed"is used, the button is considered to be partially pressed.
As an example, the mute button on an audio player labeled "mute" could indicate that sound is muted by setting the aria-pressed state true. The label of a toggle button should not change when its state changes. In our example the label remains "Mute" with a screen reader reading "Mute toggle button pressed" or "Mute toggle button not pressed" depending on the value of aria-pressed. If the design were to call for the button label to change from "Mute" to "Unmute," a toggle button would not be appropriate, so the aria-pressed attribute would be omitted.
Keyboard interactions
| Key | Function |
|---|---|
| Enter | Activates the button. |
| Space | Activates the button |
Required JavaScript Features
Required event handlers
onclick- : Handles the event raised when the button is activated using a mouse click or touch event.
onKeyDown- : Handles the event raised when the button is activated using the Enter or Space key on the keyboard. (Note not the deprecated onKeyPress)
Examples
Basic button example
In this example, a span element has been given the button role. Because a <span> element is used, the tabindex attribute is required to make the button focusable and part of the page's tab order. The included CSS style is provided to make the <span> element look like a button, and to provide visual cues when the button has focus.
The handleBtnClick and handleBtnKeyDown event handlers perform the button's action when activated using a mouse click or the Space or Enter key. In this case, the action is to add a new name to the list of names.
Try the example by adding a name to the text box. The button will cause the name to be added to a list.
HTML
<h1>ARIA Button Example</h1>
<ul id="nameList"></ul>
<label for="newName">Enter your Name: </label>
<input type="text" id="newName" />
<span role="button" tabindex="0">Add Name</span>
CSS
[role="button"] {
padding: 2px;
background-color: navy;
color: white;
cursor: default;
}
[role="button"]:hover,
[role="button"]:focus,
[role="button"]:active {
background-color: white;
color: navy;
}
ul {
list-style: none;
}
JavaScript
function handleCommand(event) {
// Handles both mouse clicks and keyboard
// activate with Enter or Space
// Key presses other than Enter and Space should not trigger a command
if (
event instanceof KeyboardEvent &&
event.key !== "Enter" &&
event.key !== " "
) {
return;
}
// Get the new name value from the input element
const newNameInput = document.getElementById("newName");
const name = newNameInput.value;
newNameInput.value = ""; // clear the text field
newNameInput.focus(); // give the text field focus to enable entering and additional name.
// Don't add blank entries to the list.
if (name.length > 0) {
const listItem = document.createElement("li");
listItem.appendChild(document.createTextNode(name));
// Add the new name to the list.
const list = document.getElementById("nameList");
list.appendChild(listItem);
}
}
const btn = document.querySelector("span[role='button']");
btn.addEventListener("click", handleCommand);
btn.addEventListener("keydown", handleCommand);
Toggle button example
In this snippet a span element is converted to a toggle button using the button role and the aria-pressed attribute. When the button is activated, the aria-pressed value switches states; changing from true to false and back again.
HTML
<button type="button">Mute Audio</button>
<span role="button" tabindex="0" aria-pressed="false"> Mute Audio </span>
<audio
id="audio"
src="https://soundbible.com/mp3/Tyrannosaurus%20Rex%20Roar-SoundBible.com-807702404.mp3">
Your browser does not support the `audio` element.
</audio>
CSS
button,
[role="button"] {
padding: 3px;
border: 2px solid transparent;
}
button:active,
button:focus,
[role="button"][aria-pressed="true"] {
border: 2px solid black;
}
JavaScript
function handleBtnClick(event) {
toggleButton(event.target);
}
function handleBtnKeyDown(event) {
// Check to see if space or enter were pressed
// "Spacebar" for IE11 support
if (event.key === " " || event.key === "Enter" || event.key === "Spacebar") {
// Prevent the default action to stop scrolling when space is pressed
event.preventDefault();
toggleButton(event.target);
}
}
function toggleButton(element) {
const audio = document.getElementById("audio");
// Check to see if the button is pressed
const pressed = element.getAttribute("aria-pressed") === "true";
// Change aria-pressed to the opposite state
element.setAttribute("aria-pressed", !pressed);
// Toggle the play state of the audio file
if (pressed) {
audio.pause();
} else {
audio.play();
}
}
const button = document.querySelector("button");
const spanButton = document.querySelector("span[role='button']");
button.addEventListener("click", handleBtnClick);
button.addEventListener("keydown", handleBtnKeyDown);
spanButton.addEventListener("click", handleBtnClick);
spanButton.addEventListener("keydown", handleBtnKeyDown);
Result
Accessibility concerns
WARNING: Be careful when marking up links with the button role. Buttons are expected to be triggered using the Space or Enter key, while links are expected to be triggered using the Enter key. In other words, when links are used to behave like buttons, adding
role="button"alone is not sufficient. It will also be necessary to add a key event handler that listens for the Space key in order to be consistent with native buttons.
Best practices
If a link performs the action of a button, giving the element role="button" helps assistive technology users understand the function of the element. However, a better solution is to adjust the visual design so it matches the function and ARIA role. Where possible, it is recommended to use native HTML buttons (<button>, <input type="button">, <input type="submit">, <input type="reset"> and <input type="image">) rather than the button role, as native HTML buttons are supported by all user agents and assistive technology and provide keyboard and focus requirements by default, without need for additional customization.