CodePark/ questions / Accessible widgets
START PRACTICINGPRACTICE
Frontend question · Accessibility › Accessible widgets

A teammate made a clickable <div> that looks like a button. What does it need to be accessible, and what should you do instead?

// Before
<div className="btn" onClick={save}>Save</div>

// After
<button type="button" className="btn" onClick={save}>Save</button>

The best fix is to use a real <button>. A <div> with onClick only works with a mouse.

To copy a button by hand, the div needs all of this:

  • role="button", so screen readers announce it as a button.
  • tabindex="0", so it can get keyboard focus.
  • A key handler. Enter must activate it. Space must activate it too, when the key is released, and you must stop Space from scrolling the page.
  • An accessible name, from its text or aria-label.
  • A visible focus style.
  • For a disabled state, aria-disabled="true", plus code that ignores clicks and keys.
  • For a toggle, aria-pressed.

And it still won't submit a form or work with the form's disabled handling.

A real <button> gives you all of this for free. If the reason was styling, reset the button's styles with CSS. Remember to keep the focus outline. This is the first rule of ARIA in action: use the native element when one exists.

  • A div with onClick works only with a mouse and has no role.
  • A fake button needs role="button", tabindex="0" and an accessible name.
  • It must activate on Enter and on Space, and Space must not scroll the page.
  • Disabled and toggle states need aria-disabled and aria-pressed handled in code.
  • The right fix is a native <button> with its styles reset.