Brief Note on Buttons, Enter, and Space
Keyboard interaction note for just one control from the entire panoply of HTML controls:
- A native
<button>fires on key down when that key is Enter. If you hold down the Enter key, it continues to fire for as long you hold Enter (or something crashes).
- A native
<button>fires on key up when that key is Space. If you do not release the Space, and also press Tab to move away from the control, the control will not fire.
There are scenarios where you want a user to be able to hold the button down, just submitting to oblivion. There are also scenarios where the user may want to be able to dismiss, perhaps if they are confirming a thing is interactive owing to poor visual design affordances and don’t want to commit.
These can blow up once a screen reader is in play. If you run Narrator/Edge, pressing Space is the same as pressing Enter, but holding either down does not repeatedly fire the event. NVDA/Firefox and JAWS/Chrome treat Space as Enter — fires on key down and holding it down continues to fire. The Windows screen readers all intercept the event, so you cannot listen for which key was pressed in your page. VoiceOver/Safari/macOS behaves as if VO was not running, and (in my script) the keyboard events are captured.
I made an example you can break.
The following button will increment a counter for each time either the Enter or Space triggers it. Try it with these interactions:
- Hold down Enter and compare the Total count and Enter count.
- Hold down Space and then (while holding down Space) pressing Tab. Compare the Total count and Space count.
- Fire up a screen reader and repeat steps 1 and 2.
I regularly encounter developers who are unfamiliar with the nuance of native control keyboard interactions. When they role-up a
<div> and try to re-create native interactions, they often introduce a mis-match, potentially messing up expectations from skilled users. Especially when native and custom controls are mixed on a page, application, site, etc.
As an aside, divergence from native controls can can be apparent in Windows High Contrast Mode / Contrast Themes. In most cases it won’t be an issue (if you specify a border), but if you mix native and custom controls on a page the color differences could be confusing.
This post does not advocate for any particular approach other than being consistent and probably managing expectations. And testing. Please, for the love of the pantheon, test.
Using VoiceOver with Safari on a Mac, if you use the VoiceOver buttons (in my case Ctrl + Alt) together with the space bar, the total count goes up, but the space and enter counts don’t.
Do you know why that is?
My script listens for keypresses. The screen reader intercepts keypress and then passes its own event to the button to trigger it.
A lot of scripts on the web work this way, which is why listening for specific keyboard actions tends to fall down when a user comes in with a screen reader.
As a comparison, if I am running JAWS and press Enter, the total count increments but not the Enter count. If I press Alt + Enter, then the Enter count also increments because it is being passed through directly to the button. The same is true if I press JAWS Key + 3 (which activates the JAWS pass-through), and then press Enter — the Enter count increments.
Interesting indeed, so, now that you know the issue at hand, what do you think may be the best approach to let the user know about these issues? I mean, in the end if I’m not able to have a solution to fix them all, then I better keep the user in the loop of some unexpected behaviors (right?).
Since I’m quite new to a11y, I can’t really think of a good semantic-html approach that helps the user in that regard. But, on the other hand, given that people using readers tend to be experienced one, maybe they are already aware of this kind of “unexpected behaviors”, so, there’s no actual need of letting them know about what their readers do (right?). What do you think?
Your comment implies you are considering the screen reader use case, so I am answering as if that is the case.
Interesting indeed, so, now that you know the issue at hand, what do you think may be the best approach to let the user know about these issues?
I mean, in the end if I’m not able to have a solution to fix them all, then I better keep the user in the loop of some unexpected behaviors (right?).
The solution is to not rely on non-native controls and/or not rely on script to capture keyboard events. The only way you could notify the user of unexpected behaviors is to test across all screen reader and browser combinations, potentially across versions, along with all interaction types.
Since I’m quite new to a11y, I can’t really think of a good semantic-html approach that helps the user in that regard.
Do not rely on non-native controls and/or do not rely on script to capture keyboard events.
But, on the other hand, given that people using readers tend to be experienced one…
This is very risky assumption. Screen reader users tend to be as comfortable with screen readers (and computers) as the general public overall. A mix of highly skilled and not, distracted and focused, frustrated and chill, comfortable with technology and not, using top hardware and old kit.
What do you think?
I think using native HTML controls and avoiding listening for specific keyboard events is a safe starting point. For example, remember that
<button>gets you the keyboard support for free.