Inaccessible button patterns.

Buttons must use the <button> element or role="button" with full keyboard support. Using <div> or <span> for buttons is a common accessibility failure.

WCAG 4.1.2Level A5 min

The problem

A <div> styled to look like a button is one of the most common accessibility anti-patterns. To a sighted mouse user it works fine; to everyone else it’s broken—it’s not in the tab order, doesn’t respond to Enter or Space, and isn’t announced as a button. Native <button> gives you keyboard operability, focus, role, and state for free (WCAG 4.1.2); reaching for a div trades all of that away for nothing.

The fix

Fails 4.1.2
<div class="btn" onclick="submit()">Submit</div>
<span onClick={handleClick} style={{cursor:'pointer'}}>Cancel</span>
Passes
<button type="submit" onClick={submit}>Submit</button>
<button type="button" onClick={handleClick}>Cancel</button>

Step by step

  1. Use <button> for actions and <a href="..."> for navigation — never use <div> or <span>.
  2. Always set type="submit" or type="button" to prevent unexpected form submission.
  3. If you must use a div (e.g., in a legacy system), add: role="button", tabindex="0", and handle both click and keydown (Enter and Space).

Common mistakes

  • Using <div> or <span> with onclick as a button.
  • Forgetting type="button" inside a form, causing accidental submits.
  • Re-implementing a div “button” but only handling click, not keydown.
  • Disabling a button visually with CSS while leaving it focusable and clickable.

How to test for it

  • Tab to the control—a real button is reachable and activates on Enter and Space.
  • Check the accessibility tree shows role “button” with a name.
  • Run an automated scan for clickable elements that aren’t real controls.

In your framework

// Correct — native button
<button type="button" onClick={handleClick}>Cancel</button>

// If forced to use a non-button element:
<div role="button" tabIndex={0}
     onClick={handleClick}
     onKeyDown={e => ['Enter', ' '].includes(e.key) && handleClick()}>

Questions

What's wrong with a div with onclick?

Divs aren't in the tab order, don't fire on Enter/Space, and aren't announced as buttons by screen readers. Native <button> handles all of this automatically.

Find it on your site.

Scan a page and see every place this issue appears, with the element and the fix.

Scan your site