I'm trying to add accessibility to my website, but I'm running into a weird issue with Firefox's accessibility scanner. I've put onclick
and onkeydown
handlers on my interactive elements, but onkeydown
doesn't seem to be enough; Firefox is telling me "Focusable elements should have interactive semantics." The [Learn More] link provided in the notice sends me to this page, which recommends a keydown or keyup event handler... which is already in the code. What am I missing here?
Here's a sample code I used to test the issue:
<img
src="https://www.google.com/logos/doodles/2022/seasonal-holidays-2022-6753651837109831.8-ladc.gif"
alt="Google"
title="Google"
tabindex="0"
onclick="alert('Google')"
onkeydown="alert('Google')">
In Firefox 108's Developer Console, under the Accessibility tab, using "Check for issues" for all issues gives me a notice on this element, saying "Focusable elements should have interactive semantics." despite the fact that onkeydown
is defined and performs the same action as onclick
.
EDIT: This question is not a duplicate of What does "Focusable Elements Should Have Interactive Semantics" mean in a figure? because that question regards an incorrect use of the role
and aria-label
attributes in a link, whereas my problem (as explained by the answer I've marked as correct, thank you!) was completely missing the role
attribute and better resolved by wrapping this in a button.
CodePudding user response:
The key thing here in the error statement:
Focusable elements should have interactive semantics.
is the word "semantics".
semantics refers to what an element actually "means" or "does" in the context of the page. Specifically, we are talking about the role of an element as exposed to the operating system's underlying accessibility API. An img
element (providing it as alt
text as you have correctly given it) has default role img
(which is obvious, I hope - that comes from the table on this page), which you can view in the ARIA specification. I won't quote anything from that as what's most important in this context is what's not there. Basically, an image is not expected to be interactive - unlike elements with different roles such as button
.
If you were to actually test your page with a screenreader - something I would highly recommend every front end developer does with some regularity - you would see the problem. Yes, knowing how your application behaves, you can press a key and have the intended functionality happen. But there's nothing in your HTML that implies that anything interactive will happen here - it's just an image, they're not expected to be interactive. So a screenreader will not announce anything to the effect of "oh by the way you can click on this" (or press enter or whatever) (actually from memory NVDA says "clickable" for elements with click
handlers - but other screenreaders such as Voiceover won't, so you shouldn't rely on this. Even knowing the element is "clickable", users without a mouse or who are unable to see where they're clicking will not know how to trigger this "click".).
The solution is to give your element the correct semantics. Since this does something when you click it, and that thing isn't navigation to a new page, it strikes me that the correct role would be button
. So you could do this, adding the correct role
attribute:
<img
src="https://www.google.com/logos/doodles/2022/seasonal-holidays-2022-6753651837109831.8-ladc.gif"
alt="Google"
title="Google"
tabindex="0"
onclick="alert('Google')"
onkeydown="alert('Google')"
role="button">
This would be a big improvement - I'd expect it to no longer bring up the error you're seeing, as well as to be much more usable to users with assistive technologies.
But, whenever you find yourself using a role
which corresponds to an alternative HTML element - and in this case it will not surprise you to know that the button
role is automatically applied to the HTML <button>
element - you should ask yourself if there's any good reason why you can't just use the correct element.
Only you can answer that question, but I'd be very surprised if such a reason existed. At worst, using a <button>
may change your styles, but I'm assuming you have control of the CSS so you can update that as needed.
You do still want the image there because that's seen by sighted users so screenreader users should be told about it the same. What I would do is wrap the image in a button, attach the onclick
handler to that button, and remove both the tabindex
and the onkeydown
, because one of the nice things about using the correct HTML element is that browsers handle most of the behaviour for you, in this case making buttons be in the tab order and trigger their click
effect whenever Enter or Space is pressed when focused.
So this would be in my opinion the best way to code this:
<button onclick="alert('Google')">
<img
src="https://www.google.com/logos/doodles/2022/seasonal-holidays-2022-6753651837109831.8-ladc.gif"
alt="Google"
title="Google"
>
<button>
and you should get everything you need, including being accessible "for free" (and the button having the image's alt text as its "accessible name"), and at worst just have to add/update some styles.