A button cannot be reached with Tab
A pointer-only control prevents keyboard users from saving their work.
The problem
Keyboard users cannot save their work.
What happens Tab skips the Save control. Read moreRead less
A settings screen has a Save control styled like a button. Clicking it saves the form, but pressing Tab moves from the last field straight to the footer.
Why it fails A div with a click handler, not a button. Read moreRead less
The control is a div with a click handler. It has no native button role or keyboard activation.
Who is affected Keyboard and voice users, stuck before Save. Read moreRead less
A keyboard user cannot complete the same action available to a pointer user. Voice commands may also lack a reliable control name.
What automation and AI miss role="button" passes a scan. Enter still does nothing. Read moreRead less
A scanner may flag a clickable element, but a clean scan after adding role="button" does not show that Enter and Space work once, focus is visible, or the save result is communicated. Generated markup still needs interaction testing.
Try it
Add it to the cart with Tab and Enter.
Tab to “Add to cart”, then press Enter or Space.
In cart: 0
A recreated demo. The broken version is intentionally inaccessible.
The fix
Replace the div with a native button, and keep its look.
- 1Use
type="button"for a local action andtype="submit"to send a form. - 2Keep the existing styles on the
button; reset only what conflicts. - 3Announce the result in a status region that is already on the page.
<div class="save-control" onclick="saveSettings()">Save changes</div><div class="save-control" role="button" tabindex="0" onclick="saveSettings()">Save changes</div>html
<button type="button" class="save-control">Save changes</button><p id="save-status" role="status"></p>css
.save-control { font: inherit; /* Keep the existing padding, colors and radius here. */}.save-control:focus-visible { outline: 3px solid var(--focus-ring); outline-offset: 3px;}js
const button = document.querySelector('.save-control');button.addEventListener('click', async () => { await saveSettings(); document.getElementById('save-status').textContent = 'Settings saved.';});Why this works
A div is not in the tab order, has no role, and ignores Enter and Space. It looks like a button only to people who can see it and use a pointer.
A click handler on a button also runs for Enter and Space, so no key handling is needed. The status region must be in the page before its text changes, or the result may not be announced.
The patch that is not a fix
This is the change scanners and code assistants often suggest. The control can now be focused and is announced as a button, but Enter and Space still do nothing. To finish the job by hand you would need key handlers, Space firing on key release, scroll prevention and a disabled state. A native button already does all of this.
Implementation decisions
A button inside a form submits by default. Use type="button" for a local action and type="submit" for submission. For a toggle, keep the label stable and expose aria-pressed. If the control takes the user to another page, use a link instead.
Keep the existing font, padding and shape on the native element. Browsers add their own button styles, so reset what conflicts with your design rather than going back to a div.
To stop the problem returning, make the native button the default in your component library. In code review, ask whether a control performs an action or navigates to another page: a button for an action, a link for navigation.
Verify the fix
5 checks, no mouse.
Record the OS, browser and assistive-technology versions, the build, the date, and the actual result of each step. Repeat after the shared button component changes.
Limits
This is a starting pattern, not a guarantee for every application. The snippets omit application-specific data handling. Test the complete journey with your target assistive technology.
This is a recreated teaching example, not a finding about a named client. The code is a starting pattern: test it in your own product. No completed assistive-technology test is claimed here.
References: www.w3.org
Keep this fixed as your code changes.
Turn guides like this into rules your coding agents and CI follow, then have the result retested with a keyboard and screen readers.