DEV Community

Cover image for 5 most frequent A11y Mistakes
Daniel Macák
Daniel Macák

Posted on

5 most frequent A11y Mistakes

1. Always relying on aria-label 😳

If you are guilty of this mistake, I don't blame you since I fell into the same trap myself. People are only too readily using aria-label whenever they want to provide additional context, but they underestimate how careful they have to be with it.

First of all you might not even need it at all. Consider this:

<section aria-label="Quiz answers">
  <h2>Quiz answers</h2>
Enter fullscreen mode Exit fullscreen mode

This example is pretty simplistic, but it goes to show that your HTML structure is often enough to provide screen reader (SR) users the needed context. A <section>, as MDN and the HTML Standard tell us, is usually accompanied by a heading and SRs rely on that. In practice, even when a SR user navigates a webpage by regions instead of headings (regions are special areas on the page like <nav>, <main>, <section> etc.) the <h2> will be read together with the <section> by the SR even without the aria-label.

But there is a much more sinister side of things than just needlessly slapping useless aria-labels everywhere, they can actually betray you! 😕 Check this out:

<ul>
  <li aria-label="Option 1 is the correct answer, and you did not vote for it">
    <span aria-hidden>Option 1</span>
  </li>
Enter fullscreen mode Exit fullscreen mode

This looks completely valid right? We provide additional context in aria-label and hide the <span> because we don't want 'Option 1' to be read twice. But guess what, the whole list will be completely ignored in both NVDA and JAWS screen readers! Now why the hell is that?

The issue has 2 components:

  1. The list item has no SR-visible content thanks to aria-hidden. That's I guess anticipated, but...
  2. The aria-label, which was supposed to work around the hidden content, is actually invalid on <li>!

Not only isn't aria-label compatible with the list item element, it usually can't be used on such ubiquitous elements like <div> and <span> either! I bet you didn't see that coming, and I certainly hadn't in the past.

So when can you use it then? MDN says it clearly (emphasis mine):

... in practice however, it is supported only on interactive elements, widgets, landmarks, images, and iframes.

Meaning that if your <div> has eg. a role="button", aria-label is gonna work, but if it is plain old div, the aria-label will be disregarded. And as my example shows, this can go beyond the SR not providing the additional context, it can actually lead to a whole section of content being hidden from the SR user when particular conditions are met.

2. Disabling form elements

A lot has been written on this topic and I recommend Adrian Roselli's article for summary. I have basically 2 issues with disabling form elements which imo are relevant to both SR and non-SR users.

They are hard to see 🙈

For some reason, Web Content Accessibility Guidelines (WCAG) don't require the same color contrast standard for disabled elements as for the rest of the page, which then allows for such designs:

Not a very visible disabled button

If your sight is 20/20 you'll have no problem reading this button but so many other people just won't see the text and neither even the button itself, given its low contrast with the white background.

They provide no explanation

Ask yourself an honest question: How often, when you disable form elements or any controls for that matter, do you also provide an explanation on why they are disabled? Exactly.

It's super annoying and confusing not to know why and not just for assistive tech users, though it of course hits them the hardest. It might be logical and perfectly understandable to us, programmers, that eg. a submit button should stay disabled until all form fields are valid, but it's not as cut and dried for our users.

3. Underestimating SR differences

There are big differences between SRs on multiple levels. The obvious one is the way SRs read webpages. Remember that aria-label gotcha from #1 above? It actually worked in VoiceOver on Mac and the aria-labeled content was read just fine but it was completely broken in the Windows SRs - NVDA and JAWS. Other times when I coded the first version of one highly interactive feature and used primarily NVDA to develop it, it worked great there but didn't work at all with VoiceOver.

In terms of development, your best bet is to follow the WAI-ARIA standard and use the Authoring Practices Guide and you should be in the clear in most cases.

But that doesn't mean you can skip the testing and you should absolutely test on multiple platforms and SRs:

  • Windows, ideally both NVDA and JAWS due to their big market share, based on the WebAIM 2024 Survey
  • Mac with VoiceOver
  • iOS with VoiceOver
  • Android, eg. with Talkback

I'd say this is the minimal suite but I totally understand if it's too much for one developer to do every day, because of course it is. What helps is that over time you'll learn which things require a full (re)test and of course your company's a11y testing/auditing process should have your back, but that's its own big topic which I won't expand on here.

4. Not knowing how users use SR 🤔

I see it a lot with people who are just starting to play with screen readers, be it developers or designers, having a very fuzzy idea of how one navigates the presented content beyond pressing the Tab key. This of course leads to less than ideal implementations, same as with building a product and not understanding your audience.

There are many ways to navigate a webpage or any other content with screen readers. Most people use headings to make sense of the content. Jumping to specific regions, navigating by links, forms or the Find feature are all important tools for the SR users.

But it's not just about which content "anchors" can be utilized. If we come back to the SR differences for a second, we'll discover very different techniques of navigating. VoiceOver users can use a so called Rotor to switch between different types of "anchors" (regions, links, headings, ...) and even search among them to reach their desired destination. NVDA on the other hand works very different to VO in that it doesn't operate in one all-encompassing mode but rather in multiple and when a user eg. wants to operate a form, she needs to switch from browsing to interactive.

SRs on mobile are their own chapter because users operate them very differently to desktop and without going into much detail, they really put things into perspective (more on that in #5).

Understanding all this is key in order to implement accessible apps and it will help you know what and why you are doing when addressing a11y issues. Luckily, there are great resources on getting this kind of understanding:

5. Misunderstanding the purpose of the Tab key

This is kinda my favorite one since I see it quite a lot and I also feel understanding it will make the lives of us all so much easier. So let's join hands and say it all together: Tab key is not for navigating all interactive elements! 🤯

Feeling funny now? Once the dizziness passes, you might be thinking "What the hell did I just say?". It might make no sense to you. But in reality it makes a lot of sense. Consider the example below; just click into the Codepen (I stole it from MDN) and Tab all the way through to the current tabpanel (content of the current tab).

That took a little too many Tab presses didn't it? Sure, all tabs are interactive and should be focusable but did we need to go through all of them? And now imagine there were 10 tabs, not 5. Or even better, imagine you'd be trying to get over a list of 1000 emojis to reach a content below it. And imagine doing that on mobile, where Tab is performed by swiping left and right! 🤯 That'd be more than a little tedious, right?

This example gets to show that it's actually NOT the purpose of the Tab key to go through all interactive elements on the page, but rather browse quickly through the page's content. If the user decides to interact with the content like the tablist from above, she can do so with the arrow keys.

It's like walking down a street, knocking on the door of the houses alongside it and deciding on the spot whether to enter or go to the next one. Going from house to house is the Tab key pressing and entering the house is the Arrow keys (don't quote me on that once they apprehend you for trespassing).

So this is how it should look in practice, the first Tab keypress moves focus to the currently active tab, second Tab press goes to the tabpanel (tab content). Neat!

Again, a great resource on how to get this kind of interactivity is the Authoring Guidelines from W3C and I can't recommend it highly enough.

That's it!

Alright, lemme know which a11y transgression bothers you the most and what you would put into your Top 5 list!

Top comments (0)