We'd like to set Google Analytics cookies to learn how people use the Knowledge Base, so we can improve it. We set them only if you accept.

Skip to main content
Digital Accessibility Knowledge Base

Button

UI pattern

A button triggers an action on the current page. An accessible button carries the button role, an accessible name, and a reliable disabled state, and keyboard users can reach and activate it.

A button differs from a link, which navigates to another page, view, or resource rather than performing an action on the current page.

Sighted users learn what a button does from its label, its visual presentation, and its context. Assistive technology users depend on button labels, semantics, properties, and states being conveyed to the assistive technology they use.

The following HTML elements are semantic buttons that natively convey their button role and other essential information to assistive technologies: <button>, <input type="button">, <input type="submit">, <input type="image">, and <input type="reset">.

Any of the native HTML semantic buttons automatically conveys its button role, name, and disabled state to assistive technology and is keyboard operable. Native HTML buttons go beyond what WCAG success criteria strictly require, so use them whenever possible.

A user can activate a native HTML button in many ways: by pointing and clicking with a mouse or other pointing device, by tapping a touch screen, by issuing a voice command through assistive technology that supports it, or by pressing the Enter or Space key. Each of these results in a click event that JavaScript can handle to perform the action.

Activating a button with any kind of pointing device can be canceled. The click event occurs when the user releases the mouse button, lifts the finger that tapped the touch screen, or completes whatever action their device requires to point and "click." To cancel, the user moves the pointer off the button before releasing it.

Current accessibility standards do not require a way to cancel button activation with a keyboard, but native HTML buttons provide one. The Enter key activates a button as soon as it's pressed. The Space key doesn't activate a button until it's released, and moving focus away from the button while holding the key down cancels the activation.

The Examples section discusses the ARIA attributes and JavaScript a generic HTML element needs to emulate a native HTML button.

This article covers the base accessibility requirements of buttons, however they're used. Some specialized button applications have additional accessibility requirements. Their entries are listed in Related Patterns.

When to Use

Use a button when:

  • The control triggers an immediate action on the current page, such as submitting a form, saving, opening or closing a dialog, or confirming or canceling a choice.

Don't use a button when:

  • The control takes the user to another page, view, or resource. Use a link so assistive technology users are aware that acting on it will cause a change of context.
  • The control lets the user enter a value or select one from a set. Use a combobox, listbox, or another form of input.

Activating a button should never cause an unexpected change of context.

Examples

Code in this section is meant to demonstrate techniques rather than requirements and lacks features needed in a production application.

A native HTML button, such as the one in the following example, is accessible by default. The JavaScript that performs its action only needs to handle the click event for the button to be operable by all users. It's in the tab order and keyboard operable unless its disabled attribute is set.

Native button HTML
HTML
<button id="save-button">Save changes</button>
Native button JavaScript
JavaScript
document.getElementById('save-button').addEventListener(
    'click', () => { /* Save changes */ }
)

A custom button requires additional attributes and JavaScript to duplicate the built-in accessibility of the <button> element, as in the following simplified example.

To emulate a native HTML button, this custom button requires several code additions that come for free with <button>:

  • The attribute role="button" is set to let assistive technology users know that the element is a button.
  • The attribute tabindex="0" places the button in the tab order, allowing keyboard users to focus on it.
  • The "Save changes" action is handled on the click event.
  • Keyboard event handlers allow button activation by triggering a click event with the Enter keydown or Space keyup events.
  • JavaScript can disable the button with saveButton.disabled = true and re-enable it with saveButton.disabled = false.
  • Whenever the button is disabled, its action is prevented, the attribute aria-disabled="true" is set, and the button is removed from the tab order.
Custom button HTML
HTML
<div id="save-button" role="button" tabindex="0">Save changes</div>
Custom button JavaScript
JavaScript
class CustomButton {
    #element;


    constructor(element) {
        this.#element = element;
        this.#initialize();
    }


    #saveChanges() {
        /* code to save changes */
    }


    #initialize() {
        this.#element.setAttribute("role", "button");
        this.#element.tabIndex = 0;
        this.#element.addEventListener("click", (event) => {
            if (this.disabled) {
                event.preventDefault();
                event.stopImmediatePropagation();
                return;
            }
            this.#saveChanges();
        })
        this.#element.addEventListener("keydown", (event) => {
            if (this.disabled) return;
            if (event.key === "Enter") {
                event.preventDefault();
                this.#element.click();
            }
            else if (event.key === " ") {
                // prevent default page scroll
                event.preventDefault();
            }
        })
        this.#element.addEventListener("keyup", (event) => {
            if (this.disabled) return;
            if (event.key === " ") {
                event.preventDefault();
                this.#element.click();
            }
        })
    }


    get disabled() {
        return this.#element.getAttribute("aria-disabled") === "true";
    }


    set disabled(trueOrFalse) {
        const disable = Boolean(trueOrFalse);
        this.#element.setAttribute("aria-disabled", String(disable))
        this.#element.tabIndex = disable ? -1 : 0;
    }


}


const saveButton = new CustomButton(
    document.getElementById('save-button')
);

Structure and Semantics

A button is an interactive element that conveys its purpose to assistive technology through the button role and its accessible name, which together tell users what the button does and how to use it.

A button has no structure. The element <input type="button"> is defined by its attributes. A <button> element can have content, but assistive technologies use that content only to compute the button's accessible name. They treat the subtree of any element with the button role as presentational.

ARIA attributes can add semantic information to convey special-purpose properties or state to assistive technology:

AttributePurpose
aria-controlsIdentifies an element the button controls
aria-disabledReports the button's disabled / enabled state
aria-expandedReports the visibility state of the content the button controls
aria-haspopupReports the presence and nature of a popup the button controls
aria-labelProvides an accessible name when text content can't provide one
aria-pressedReports the pressed state of a toggle button

Role

A button must expose the button role to assistive technology so that users know its purpose and how they can interact with it.

The HTML <button> and <input type="button"> elements expose the button role implicitly, requiring no additional ARIA. When you have to build a button from a different element, such as a non-semantic element or a semantic element that allows the button role, set role="button" on it explicitly.

Without the button role, screen readers announce a button as plain, non-interactive content or, with a different role, as the wrong kind of element. Users won't know its purpose or how to interact with it.

The following elements implicitly carry the button role:

  • <button> and <input type="button"> can be used anywhere on a web page.
  • <input type="image"> and <input type="submit"> can be used to submit a form.
  • <input type="reset"> can be used to reset a form.
Button has the correct role

Reported as: Element has incorrect role

A button must carry the button role.

Severity: Critical

StandardSuccess CriterionReference
WCAG 2.24.1.2 Name, Role, Value (A)For all user interface components, the name and role can be programmatically determined; states, properties, and values that can be set by the user can be programmatically set; and notification of changes to these items is available to assistive technologies.
EN 301 5499.4.1.2 Name, Role, ValueSame as the WCAG text.
Section 5081194.21(d)Sufficient information about a user interface element including the identity, operation and state of the element shall be available to assistive technology. When an image represents a program element, the information conveyed by the image must also be available in text.
Button role is applied to the interactive element

Reported as: Incorrect root element

Sanity check. Evinced checks that the button role sits on the selected element, the one users focus and operate, rather than on one of its descendants. This check runs on every UI pattern, not only on buttons.

The button role should sit on the same element that receives focus and handles activation.

When the role sits on a descendant while a wrapper takes focus or handles the click, screen readers announce a button that isn't the element users operate, and keyboard users may reach a control that doesn't respond to Enter or Space.

Put the role, the accessible name, the ability to focus, and the activation handling on that one element, and keep any wrapper free of roles and handlers. If the test selected a wrapper by mistake, select the button itself and run the test again.

Button Name

By default, a button is named by its text content, and that name should say what the button does. Without a meaningful name, screen readers announce only "button," and users can't know what it does or tell it apart from other buttons.

Has an accessible name

Reported as: Accessible name

A button must have an accessible name that identifies what it does.

Give the button a name through visible text, an image's alt text, or an aria-label attribute, and keep the name short and specific to the action it performs.

Severity: Critical

StandardSuccess CriterionReference
WCAG 2.24.1.2 Name, Role, Value (A)For all user interface components, the name and role can be programmatically determined; states, properties, and values that can be set by the user can be programmatically set; and notification of changes to these items is available to assistive technologies.
EN 301 5499.4.1.2 Name, Role, ValueSame as the WCAG text.
Section 5081194.21(d)Sufficient information about a user interface element including the identity, operation and state of the element shall be available to assistive technology. When an image represents a program element, the information conveyed by the image must also be available in text.

Disabled

A button must convey its disabled state to assistive technologies.

Avoids conflicting disabled states

Reported as: Conflicting disabled values

A button must declare its disabled state one way only: the disabled attribute on a native <button> or <input type="button">, or aria-disabled on a custom button.

When a native button carries aria-disabled instead of disabled, it stays operable and in the tab order while assistive technology reports it as disabled. When both attributes are set and disagree, assistive technology can report a state the browser doesn't enforce. Either way, screen reader users are told the wrong thing about whether the button works.

Use disabled alone on a native button and aria-disabled alone on a custom button, removing it or setting it to false when the button is enabled again.

Severity: Serious

StandardSuccess CriterionReference
WCAG 2.24.1.2 Name, Role, Value (A)For all user interface components, the name and role can be programmatically determined; states, properties, and values that can be set by the user can be programmatically set; and notification of changes to these items is available to assistive technologies.
EN 301 5499.4.1.2 Name, Role, ValueSame as the WCAG text.
Section 5081194.21(d)Sufficient information about a user interface element including the identity, operation and state of the element shall be available to assistive technology. When an image represents a program element, the information conveyed by the image must also be available in text.
Custom button uses aria-disabled rather than disabled

Reported as: Element does not support the disabled attribute

A button built from an element that does not natively support the disabled attribute must convey its disabled state with aria-disabled instead.

When the disabled attribute is applied to an element that doesn't support it, such as a custom button built from a <div> or <span>, browsers ignore it. The button stays operable even though it looks disabled, so keyboard and screen reader users can still trigger an action meant to be unavailable. Use aria-disabled="true" instead, and block activation in the button's event handlers while it's disabled.

Severity: Serious

StandardSuccess CriterionReference
WCAG 2.24.1.2 Name, Role, Value (A)For all user interface components, the name and role can be programmatically determined; states, properties, and values that can be set by the user can be programmatically set; and notification of changes to these items is available to assistive technologies.
EN 301 5499.4.1.2 Name, Role, ValueSame as the WCAG text.
Section 5081194.21(d)Sufficient information about a user interface element including the identity, operation and state of the element shall be available to assistive technology. When an image represents a program element, the information conveyed by the image must also be available in text.
Disables only elements that support it

Reported as: Element type does not support disabled state

An element in a button must carry disabled or aria-disabled only when its role supports a disabled state.

When the state sits on an element whose role has none, such as a wrapper, a list item or a heading, assistive technology may drop it or report it on something users can't operate, while the control that really is unavailable is still reported as available.

Remove the attribute from that element, and set the disabled state on the control itself, using an element or role that supports it, such as a native <button>.

Severity: Serious

StandardSuccess CriterionReference
WCAG 2.24.1.2 Name, Role, Value (A)For all user interface components, the name and role can be programmatically determined; states, properties, and values that can be set by the user can be programmatically set; and notification of changes to these items is available to assistive technologies.
EN 301 5499.4.1.2 Name, Role, ValueSame as the WCAG text.
Section 5081194.21(d)Sufficient information about a user interface element including the identity, operation and state of the element shall be available to assistive technology. When an image represents a program element, the information conveyed by the image must also be available in text.

Forbidden Interactive Children

Nested interactive elements create ambiguity for all users, who can't be certain which element will respond to their interaction.

Interactive elements are not nested

Reported as: Forbidden interactive children; Nested interactive elements

A button must not contain or be nested inside another interactive element, such as a link or other button.

A button has no accessible children. An interactive element nested inside it is presentational, so screen reader users can't perceive or operate it as a control.

Don't nest interactive elements.

Severity: Serious

StandardSuccess CriterionReference
WCAG 2.24.1.2 Name, Role, Value (A)For all user interface components, the name and role can be programmatically determined; states, properties, and values that can be set by the user can be programmatically set; and notification of changes to these items is available to assistive technologies.
EN 301 5499.4.1.2 Name, Role, ValueSame as the WCAG text.
Section 5081194.21(d)Sufficient information about a user interface element including the identity, operation and state of the element shall be available to assistive technology. When an image represents a program element, the information conveyed by the image must also be available in text.

Relationships

Buttons often control other elements to create user interfaces. When a button's presentation conveys a relationship to another element, the button should also convey it to assistive technology by setting aria-controls to the ID of the controlled element.

aria-owns

A button is a single control, not a container. Its children are presentational, so nothing inside a button reaches assistive technology except as part of its accessible name.

Avoids aria-owns

Reported as: Avoid aria-owns

General check. Evinced checks that the button doesn't use aria-owns to claim elements elsewhere in the document as its children. This check runs on every UI pattern, not only on buttons.

A button should not use aria-owns.

When a button owns an element, that element becomes one of the button's children, and a button's children are presentational. Assistive technology users perceive the owned element only as part of the button's name and can't operate anything interactive inside it.

Remove aria-owns and keep the content outside the button. When the button operates that content, reference it with aria-controls instead.

Operation

A button must be operable with both a pointer and a keyboard. Clicking or tapping the button activates it. On a keyboard, the Tab key moves focus to and away from a button, and pressing Enter or Space activates it.

Semantic HTML buttons provide this keyboard behavior automatically. A custom button built with role="button" must reproduce it: Add tabindex="0" so the element joins the tab order, and add event listeners to enable activation with the Enter or Space key. By convention, a button is activated on an Enter keydown event and a Space keyup event.

Focus Sequence

A button must be in the tab order and reachable with the Tab key when it's enabled, and should be removed from the tab order when it's disabled.

Button is reachable by keyboard

Reported as: Keyboard accessible

A button must be reachable in the keyboard tab order.

When the button is built from markup that isn't focusable, such as a <div> or <span>, it may be clicked with a pointer, but keyboard users can't reach it or operate it.

A native <button> element is focusable by default. A custom button needs a tabindex="0" attribute to join the tab order.

Severity: Critical

StandardSuccess CriterionReference
WCAG 2.22.1.1 Keyboard (A)All functionality of the content is operable through a keyboard interface without requiring specific timings for individual keystrokes, except where the underlying function requires input that depends on the path of the user's movement and not just the endpoints.
EN 301 5499.2.1.1 KeyboardSame as the WCAG text.
Section 5081194.21(a)When software is designed to run on a system that has a keyboard, product functions shall be executable from a keyboard where the function itself or the result of performing a function can be discerned textually.
508 Trusted Tester2.1.1-keyboard-access, 4.AAll functionality can be accessed and executed using only the keyboard.
Button is removed from tab order when disabled

Reported as: Disabled element focusable

An HTML <button> element is removed from the tab order when it's disabled, and a custom button should be too. When a disabled button stays in the tab order, keyboard users land on a control they can't activate. Screen reader users are told the button is disabled, but the tab stop may provide no benefit.

For a custom button, set tabindex="0" when it's enabled and set tabindex="-1" when aria-disabled="true" is set.

Severity: Minor

This issue is classified as "Best Practice," meaning it isn't tied to a specific WCAG success criterion or any other regulation or standard; however it still affects the experience of some users. These issues fall outside formal compliance requirements, yet addressing them improves usability and accessibility in practice.
The interactive element is in the tab order

Reported as: Focusable offset

The element that is actionable and carries the button role must be the element that receives focus, not one of its descendants.

When a descendant takes focus instead, keyboard users can tab to the control but may not be able to activate it with Enter or Space.

HTML <button> and <input> elements that aren't disabled are in the tab order by default. For a custom button, set tabindex="0" on the element that triggers the action and carries the button role.

Severity: Minor

StandardSuccess CriterionReference
WCAG 2.22.1.1 Keyboard (A)All functionality of the content is operable through a keyboard interface without requiring specific timings for individual keystrokes, except where the underlying function requires input that depends on the path of the user's movement and not just the endpoints.
EN 301 5499.2.1.1 KeyboardSame as the WCAG text.
Section 5081194.21(a)When software is designed to run on a system that has a keyboard, product functions shall be executable from a keyboard where the function itself or the result of performing a function can be discerned textually.
508 Trusted Tester2.1.1-keyboard-access, 4.AAll functionality can be accessed and executed using only the keyboard.

Keyboard Activation

Unless explicitly prevented, a click event can be triggered on any HTML element by someone using a mouse or other pointing device. Keyboard users can activate only native HTML interactive elements. Some elements, such as <a href="some-uri">, are activated with the Enter key, while others, such as <input type="checkbox">, are activated with the Space key. Unless it's disabled, a button activates with either the Enter or Space key.

For an interactive element, Enter and Space carry subtly different semantics: The Enter key most often triggers a do action, while the Space key generally triggers a select action, and a button honors both.

A button is activated on an Enter keydown event but on a Space keyup event so that a user can cancel the select action. To cancel it, the user tabs away from the button while holding the Space key down.

Operable by keyboard

Reported as: Button not activated by keyboard

Keyboard users must be able to focus on and activate a button. Otherwise, they can't use the interface.

HTML elements that implicitly carry the button role, such as <button> and <input type="button">, are keyboard operable. Any other element requires JavaScript event listeners for keyboard events that either perform the action or create a click event that triggers the action.

Severity: Critical

StandardSuccess CriterionReference
WCAG 2.22.1.1 Keyboard (A)All functionality of the content is operable through a keyboard interface without requiring specific timings for individual keystrokes, except where the underlying function requires input that depends on the path of the user's movement and not just the endpoints.
EN 301 5499.2.1.1 KeyboardSame as the WCAG text.
Section 5081194.21(a)When software is designed to run on a system that has a keyboard, product functions shall be executable from a keyboard where the function itself or the result of performing a function can be discerned textually.
508 Trusted Tester2.1.1-keyboard-access, 4.AAll functionality can be accessed and executed using only the keyboard.
Responds to Enter and Space

Reported as: Button may not be activated by keyboard

A button must respond to both the Enter key and Space.

When a button's script handles clicks but shows no handling for Enter or Space, keyboard users may press the keys a button promises and get no response. Whatever the button does is then out of their reach.

Use a native <button>, which handles both keys. On a custom button, handle Enter and Space in a keydown listener and run the same action a click runs.

Severity: Critical

StandardSuccess CriterionReference
WCAG 2.22.1.1 Keyboard (A)All functionality of the content is operable through a keyboard interface without requiring specific timings for individual keystrokes, except where the underlying function requires input that depends on the path of the user's movement and not just the endpoints.
EN 301 5499.2.1.1 KeyboardSame as the WCAG text.
Section 5081194.21(a)When software is designed to run on a system that has a keyboard, product functions shall be executable from a keyboard where the function itself or the result of performing a function can be discerned textually.
508 Trusted Tester2.1.1-keyboard-access, 4.AAll functionality can be accessed and executed using only the keyboard.
Ignores keyboard when disabled

Reported as: Disabled button keyboard activation

A button that reports itself as disabled should reject keyboard activation.

When a custom button carries aria-disabled="true" but the Enter or Space key still triggers its action, screen reader users may be confused or lose trust in the interface. When possible, use the HTML <button>, which blocks interaction automatically when disabled is set. Otherwise, block activation with JavaScript whenever aria-disabled="true" is set on a custom button.

Severity: Serious

This issue is classified as "Best Practice," meaning it isn't tied to a specific WCAG success criterion or any other regulation or standard; however it still affects the experience of some users. These issues fall outside formal compliance requirements, yet addressing them improves usability and accessibility in practice.
Button activates with Space key

Reported as: Button requires space key activation

A custom button must activate with the Space key, as a <button> element does, not just with the Enter key.

Users who expect Space to work as it does for every other button may conclude the control is unresponsive or, if they expect the ability to cancel a choice after pressing Space down, may find they can't.

Add a Space keyup event handler to activate a custom button, or use a native <button> element.

Severity: Minor

StandardSuccess CriterionReference
WCAG 2.22.1.1 Keyboard (A)All functionality of the content is operable through a keyboard interface without requiring specific timings for individual keystrokes, except where the underlying function requires input that depends on the path of the user's movement and not just the endpoints.
EN 301 5499.2.1.1 KeyboardSame as the WCAG text.
Section 5081194.21(a)When software is designed to run on a system that has a keyboard, product functions shall be executable from a keyboard where the function itself or the result of performing a function can be discerned textually.
508 Trusted Tester2.1.1-keyboard-access, 4.AAll functionality can be accessed and executed using only the keyboard.

Event Listener Type

When script in a button responds to keys, it listens for keydown or keyup. The keypress event is deprecated, and browsers don't fire it for many keys, including the arrow keys, Home, End and Escape.

Avoids the keypress event

Reported as: Deprecated keypress listener

A button's key handling should use keydown or keyup, not keypress.

When a handler listens for keypress, keys the browser doesn't send through that event go unanswered, and keyboard users find the button ignoring keys it's meant to respond to.

Replace each keypress listener with a keydown listener, and read the key from event.key.

Severity: Minor

This issue is classified as "Best Practice," meaning it isn't tied to a specific WCAG success criterion or any other regulation or standard; however it still affects the experience of some users. These issues fall outside formal compliance requirements, yet addressing them improves usability and accessibility in practice.

FAQ

Which WCAG success criteria do the button issues relate to?

Most button issues relate to 4.1.2 Name, Role, Value: the button role, an accessible name, a correctly conveyed disabled state, and no nested interactive elements. Reaching a button by keyboard, focus landing on the element that carries the role, and activating it with Enter and Space relate to 2.1.1 Keyboard.

Two criteria map to no WCAG success criterion and are best practices: removing a disabled button from the tab order, and ignoring the keyboard when a button is disabled.

Why are some button issues marked as Critical and others as Minor?

Severity reflects how much an issue gets in users' way. Critical issues stop users outright: a button with no role or name, or one that keyboard users can't reach or activate.

Serious issues mislead or confuse users, such as a wrong disabled state, nested interactive elements, or a disabled button that still responds to the keyboard. Minor issues break a convention without blocking the task, such as a custom button that ignores the Space key, focus that lands inside the button rather than on it, or a disabled button left in the tab order.

Two checks carry no severity: the general check for aria-owns and the sanity check on where the button role sits.

  • Disclosure: a button that shows and hides a region of content
  • Menu Button: a button that opens a menu
  • Dialog: a dialog that a button usually opens
  • Toggle Button: a button that switches between pressed and not pressed
  • Link: navigates to another page, view, or resource instead of performing an action