Hang scripted actions on real links and buttons
The word onclick sounds like a mouse. It is not one. SCR35 is a sufficient technique for keyboard access when used with G90, and most of the time it makes the other three unnecessary. On an anchor or a button it maps to the element's default action. The browser fires it for Enter, for Space on a button, for a tap, and for activation coming through an accessibility API. Write your handler on a real control and every input device is already handled. The part of this technique that gets skipped is what happens with script switched off, and W3C organizes its six examples entirely around that question. A link that runs a script can navigate somewhere real instead. A button that runs a script can fall back to posting its form. Neither costs much to build and both are the difference between a degraded page and a dead one.
How we find it in an audit
Reviewers work every control from the keyboard and confirm the action fires on Enter, and on Space where the control is a button. Then we look at the markup. A span with a click handler passes no test here, whatever it looks like on screen. Anchors used this way get one more check, that the href points somewhere sensible and the handler stops the page jumping when it should not. Automated tools are good at this one, since a click handler on a non-interactive element is a fact rather than a judgment, and we treat the tool's list as the start of the review.
How affected users experience it
Real controls come with meaning attached. A screen reader announces a button as a button and a link as a link, and it lists them separately. A user can pull up every link on the page, or move between controls, without reading the prose around them. A span carrying a click handler is in none of those lists. It is prose. Someone using speech input cannot ask for it by name, and someone using a switch never lands on it. Someone using a screen reader walks straight past the thing the entire page was built to get them to.
Passes vs. fails
Passes
<button type="button" onclick="runReport()">Run report</button>
<a href="/report.pdf" onclick="return openViewer(event)">Run report</a>
<!-- The anchor still downloads the report when script is unavailable. -->Fails
<span class="button" onclick="runReport()">Run report</span>
<!-- Not focusable, no role, and Enter does nothing. -->How this gets tested
The W3C publishes test rules that define what a checker looks for here.
- Iframe with interactive elements is not excluded from tab-orderA tool can check this
- Scrollable content can be reached with sequential focus navigationA tool can check this
Other ways to satisfy this rule
13 guides on this site are filed under 2.1.1 Keyboard. W3C lists this one as sufficient for that rule only alongside G90, so the pair is what passes and neither half does on its own.
- G90sufficientPair every event handler with keyboard support
- G202sufficientMake every control work with a keyboard
- H91sufficientUse native HTML controls instead of rebuilt ones
- PDF3sufficientFix the reading and tab order in PDFs
- PDF11sufficientTag PDF links so they are announced
- PDF23sufficientUse fillable form fields instead of flat text
This guide is our interpretation of W3C technique SCR35: Making actions keyboard accessible by using the onclick event of anchors and buttons. W3C publishes its techniques as guidance rather than as the standard, and says so on every one of them. The success criterion is what conformance is measured against, and a technique is one documented way to meet it.