Forms & Controls
Button (incl. toggle button)
An interactive control that triggers an action, or toggles between pressed/not-pressed states.
Last verified against WCAG 2.2 and WAI-ARIA APG 1.2 on 2026-07-02.
Implementation
button-pattern.tsx
<button type="button">Save changes</button>
<button type="button" aria-pressed="false">Favorite</button>
/* Focusable, correct role, and Enter+Space activation all come free.
aria-pressed is the one attribute a toggle button still has to set
itself — there's no native HTML "pressed" state. */Live demo
A plain action button and a toggle button (aria-pressed), fixed vs. a mouse-only broken variant.
Required roles, states & properties
| Element | Attribute | Why |
|---|---|---|
| Plain action <button> | (none required) | Native button semantics — role, focusability, and Enter/Space activation — are exposed automatically by the browser. |
| Toggle <button> | aria-pressed | Communicates on/off state as "pressed" or "not pressed." Unlike aria-expanded on a disclosure, this is never automatic — you must set and update it yourself, even on a real <button>. |
| role="button" div (custom ARIA) | role="button", tabIndex="0" | Manually restores the button role and Tab-focusability that a real <button> would provide automatically. Shown only to illustrate why this reimplementation is unnecessary. |
Keyboard interaction model
| Key | Behavior |
|---|---|
| Tab / Shift+Tab | Moves focus to and from the button in the page's natural tab order. |
| Enter | Activates the button. Fires on keydown. |
| Space | Activates the button. Fires on keyup, not keydown — this lets a user press Space, change their mind, and move focus away before releasing to cancel the action, without it firing. (Native browser behavior, not something you implement.) |
Focus management rules
- Buttons participate in the page's natural Tab order — no roving tabindex or focus trapping is involved.
- Activating a button never moves focus unless the button's documented purpose is to move focus (e.g. opening a dialog).
- A visible focus indicator must be present at every zoom level up to 200%, per SC 2.4.7 / 2.4.11.
WCAG 2.2 success criteria mapping
| SC | Name | Level | Why it applies |
|---|---|---|---|
| 2.1.1 | Keyboard | A | All functionality is operable through a keyboard interface with no specific timing. |
| 2.5.3 | Label in Name | A | The accessible name contains the visible text label. |
| 2.5.8 | Target Size (Minimum) | AA | Pointer targets are at least 24x24 CSS pixels, unless spaced, inline, or essential. |
| 4.1.2 | Name, Role, Value | A | For all UI components, name, role, and value are programmatically determinable; states and changes are announced. |