Loading Developer Playground

Loading ...

Skip to main content
Share:
ARIA ROLEโ€ขWidget Roles

button

An input that allows for user-triggered actions. Buttons are clickable elements that trigger a response when activated by the user.

Keyboard Support
Enter, Space
Default tabindex
0
Required Attributes
None

Overview

The button role identifies an element as a button to assistive technologies. When activated, it triggers an action such as submitting a form, opening a dialog, or performing a calculation.

Important: Always use the native <button> element when possible. The role="button" should only be used when you must use a different element due to styling or framework constraints.

Native <button> vs role="button"

The native <button> element provides keyboard support, focus management, and form integration automatically. Using role="button" requires you to manually implement all keyboard interactions.

Live Demo: Button Interactions

Native Button (Best Practice)

Toggle Button (aria-pressed)

Try with keyboard: Tab to focus the buttons, then press Enter or Space to activate them. Screen readers will announce these as buttons and their states.

Code Examples

Basic Usage

<!-- Basic Button with ARIA role -->
<div role="button" tabindex="0">
  Click Me
</div>

<!-- Note: Use native <button> element when possible -->
<button>I'm better!</button>

<!-- Use role="button" only when semantic HTML isn't an option -->

Keyboard Support

<!-- Accessible custom button with keyboard support -->
<div 
  role="button"
  tabindex="0"
  onclick="handleClick()"
  onkeydown="handleKeyPress(event)"
>
  Save Changes
</div>

<script>
  function handleClick() {
    console.log('Button clicked');
  }
  
  function handleKeyPress(event) {
    // Support both Enter and Space keys
    if (event.key === 'Enter' || event.key === ' ') {
      event.preventDefault(); // Prevent page scroll on Space
      handleClick();
    }
  }
</script>

Disabled State

<!-- Disabled button with aria-disabled -->
<div 
  role="button" 
  tabindex="0"
  aria-disabled="true"
  onclick="if (this.getAttribute('aria-disabled') === 'true') return false;"
  class="button-disabled"
>
  Disabled Button
</div>

<style>
  .button-disabled {
    opacity: 0.5;
    cursor: not-allowed;
    pointer-events: none;
  }
</style>

Toggle Button (aria-pressed)

<!-- Toggle button with pressed state -->
<button 
  role="button"
  aria-pressed="false"
  onclick="toggleButton(this)"
>
  <span class="icon" aria-hidden="true">๐Ÿ”‡</span>
  Mute
</button>

<script>
  function toggleButton(btn) {
    const pressed = btn.getAttribute('aria-pressed') === 'true';
    btn.setAttribute('aria-pressed', !pressed);
    
    // Update visual state
    const icon = btn.querySelector('.icon');
    icon.textContent = !pressed ? '๐Ÿ”Š' : '๐Ÿ”‡';
    btn.textContent = !pressed ? 'Unmute' : 'Mute';
  }
</script>

React Components

// React Button Component
import { useState } from 'react';

// Good: Use native button
function GoodButton({ onClick, children }) {
  return (
    <button
      onClick={onClick}
      className="px-4 py-2 bg-blue-500 text-white rounded"
    >
      {children}
    </button>
  );
}

// Only when necessary: Custom button with role
function CustomButton({ onClick, disabled, children }) {
  const handleKeyDown = (e) => {
    if (e.key === 'Enter' || e.key === ' ') {
      e.preventDefault();
      if (!disabled) onClick();
    }
  };

  return (
    <div
      role="button"
      tabIndex={disabled ? -1 : 0}
      aria-disabled={disabled}
      onClick={disabled ? undefined : onClick}
      onKeyDown={handleKeyDown}
      className={`px-4 py-2 rounded ${
        disabled 
          ? 'bg-gray-300 cursor-not-allowed' 
          : 'bg-blue-500 cursor-pointer'
      }`}
    >
      {children}
    </div>
  );
}

// Toggle Button with aria-pressed
function ToggleButton() {
  const [pressed, setPressed] = useState(false);

  return (
    <button
      aria-pressed={pressed}
      onClick={() => setPressed(!pressed)}
      className={`px-4 py-2 ${pressed ? 'bg-blue-700' : 'bg-blue-500'}`}
    >
      {pressed ? 'On' : 'Off'}
    </button>
  );
}

Keyboard Support

Spaceโ†’Activates the button

Must prevent default browser scroll behavior when implementing on custom elements.

Enterโ†’Activates the button

This is the primary activation method for form submissions.

Best Practices

โœ“

Use native <button> element whenever possible

โœ“

Provide clear, descriptive button labels

โœ“

Ensure buttons have visible focus indicators

โœ“

Support both Enter and Space key activation

โœ“

Use aria-pressed for toggle buttons

โœ“

Use aria-disabled instead of removing from tab order when disabled

ร—

Don't use role="button" on <a> elements - use <button> instead

ร—

Don't use buttons for navigation - use links (<a>) instead

ร—

Don't forget to add tabindex="0" when using role="button" on divs

ร—

Don't rely only on color to indicate button state

Supported ARIA Attributes

aria-pressed

Toggle button state (true/false/mixed)

aria-expanded

Whether controlled element is expanded

aria-haspopup

Indicates button opens a popup/menu

aria-disabled

Indicates button is disabled

aria-label

Accessible name for the button

aria-labelledby

References element(s) that label button

aria-describedby

References element(s) that describe button

aria-controls

Identifies element(s) button controls

Common Use Cases

Form submission
Dialog/modal triggers
Dropdown menus
Toggle switches
Action triggers (save, delete, edit)
Accordion panels
Tab navigation
Close/dismiss actions

Accessibility Notes

Keyboard Navigation

When using role="button" on non-button elements, you must implement keyboard support manually. Handle both Enter and Space keys, and remember to prevent default Space key behavior to avoid page scrolling.

Focus Indicators

Always provide visible focus indicators for buttons. This helps keyboard users know where they are on the page. The default browser outline is acceptable, but custom styles should meet WCAG contrast requirements (3:1 minimum).

Screen Reader Announcements

Screen readers will announce the element as a "button" along with its accessible name. For toggle buttons, use aria-pressed to communicate the current state. Screen readers will announce "pressed" or "not pressed" along with the button name.

Related Roles & Attributes

Specifications & Resources