
Uncanny A11y
Uncanny A11y êŽë š
The pun in the title is that some people pronounce the a11y numeronym as âalleyâ. That makes the full title sound like uncanny valley, the concept of human-looking things seeming almost, but not quite, human and therefore creepy.
In accessibility, the same thing can happen. Developers can try so hard to make sure something is accessible that the entire experience becomes weird, confusing, or downright unusable.
There are generally two things that contribute to this:
- thinking that using code, all the code, is the best way to make something accessible, and
- not testing with users who have disabilities.
Unfortunate Examples

These examples reflect real sites. I see them over and over. These examples also do not trigger automated accessibility checkers because they are technically doing nothing wrong.
Just tabindex Everything
Sometimes when developers first realize that screen reader users do not use a mouse (mostly), but instead rely on a keyboard, they can get a bit overzealous. These developers build a table and realize they cannot tab to individual cells on their computer. This is confirmed when testing using a screen reader. They rediscover this with lists, headings, regions, and so on.
Without knowing that screen readers have built-in controls to navigate tables (and lists and headings and regions), they believe that adding tabindex to every element guarantees keyboard access. I come in and I see the following:
<h2 tabindex="0">Do Not Do This</h2>
<table tabindex="0">
<tr>
<th tabindex="0">Author</th>
<th tabindex="0">Title</th>
<th tabindex="0">Year</th>
</tr>
<tr>
<td tabindex="0">Emma Dorothy Eliza Nevitte Southworth</td>
<td tabindex="0">The Hidden Hand</td>
<td tabindex="0">1888</td>
</tr>
</table>
This is compounded when using positive tabindex values. Many developers do not realize those items will come first in the tab order, before any other native controls and controls with tabindex="0". This can easily make the visual layout of the page fall out of sync with the page order. Some, however, do this intentionally.
Using aria-label As a Hint
The trick with aria-label is that it overrides the built-in accessible name on a standard control. Sometimes developers will add aria-label thinking it is a hint for screen reader users, not realizing that they have made a link useless or a button confusing.
In the following code the link will be announced only as Opens in a new window, the button as Cancel. The button may be confusing for a user who wants to close an alert but thinks he may be canceling an entire process instead.
<a href="http://example.com/" target="_blank" aria-label="Opens in a new window">Visit their site</a>
<button aria-label="Cancel">Close</button>
Following is an example from GitHub. When a screen reader user reads this content, she will hear Only those with Link Learn more about permission levels to this repository can merge pull requests.
<span class="status-meta">Only those with <a href="https://help.github.com/articles/what-are-the-different-access-permissions" class="tooltipped tooltipped-s" aria-label="Learn more about permission levels">write access</a> to this repository can merge pull requests.</span>
Some developers lean on aria-label to populate tool-tips, further confusing its true purpose.
Added 27 May 2022
The Mount Sinai web site employs the User1st overlay. When the overlay loads, through no action from the user, it overrides every link on the page (aardrian) (the line feed is in the User1st code):
<a href="http://giving.mountsinai.org/msorghp" target="_blank" aria-label="To make this website accessible to screen reader, press combination of alt and 1 keys.
To stop getting this message, press the combination of alt and 2 keys.">Make a Gift</a>
Unhelpful alt Text
Too often every image on a site is preceded with âphoto ofâ or âpicture ofâ. Authors generally do not know that screen readers pre-pend the announcement of alt text with âGraphicâ, so these users will hear âGraphic photo of a silver car.â
<img src="âŠ" alt="Photo of a silver car.">
<img src="âŠ" alt="Picture of a screen shot of the WIndows Mobile home screen.">
Some authors believe that every nuance of an image must be conveyed. They may write entire paragraphs to convey the contents of a photo, when all that is needed in context of the page is something as simple as âA coffee mugâ. Compounding this is when authors think that alt text is re-usable everywhere without changes, when often the point of an image will change based on its use and context.
<p>Come try our coffee!<br>
<img src="âŠ" alt="A four ounce white porcelain mug with a square handle on a matching white saucer, both resting on a dark wood table polished to a gloss; in the mug is a mound of white foam with dark edges at the rim.">
</p>
For images used as links the alt text not only needs to be brief, but it also needs to convey the point of the link. If I am linking to a bag of coffee beans on an ecommerce site, âA coffee mugâ wonât do. If I am linking to a company via its logo, then Visit our partner Enron logo sounds weird.
<p>
Visit our partner <a href="http://example.com"><img src="âŠ" alt="Enron logo"></a>.
</p>
Some outlets have applauded the efforts of Facebook to auto-generate alternative text for images so that users (or, more imporantly, brands) would not need to. The problem is that AI cannot understand the author intent of an image. Generated text also read like a machine, eg: Graphic. Image may contain: 2 people, people smiling, eyeglasses, outdoor and closeup.
<img src="âŠ" alt="Image may contain: 2 people, people smiling, eyeglasses, outdoor and closeup.">
Similarly, alternative text for an image in one part of a site might need to be different elsewhere on the same site.
Overriding Default Pronunciation
Sometimes a developer will start testing with a screen reader and decide that the way a screen reader pronounces words is wrong. When this happens, instead of accepting that maybe users donât care, they may try to code around it (and the resultant screen reader pauses for hidden content). Usually it is just a hidden span, but I have seen some robust solutions:
Please enter your
<ruby>
<rt aria-hidden="true" style="font-size: 1em"><!--Standard-->licence</rt>
<rt style="display: inline-block; width: 1px; height: 1px; overflow: hidden"><!--Phonetic-->license</rt>
</ruby>
number
It is not restricted to pronunciation. Often currencies, temperatures, time spans, dates, and so on can confuse a developer listening to it for the first time. It can be particularly taxing for users when developers make them even more verbose (and compound it by making each one a tab-stop).
<div tabindex="0" aria-label="September 16th 2016">16</div>
<div tabindex="0" aria-label="September Sixteenth Two Thousand and Sixteen">16</div>
I have also run into cases where developers truly believe every foreign word used in a sentence, including common idioms, must be wrapped in a container with a lang attribute. The frustration comes when the screen reader pauses at the container, not to mention when the word sounds different than it has every other time for the user.
<p>I hope this <span lang="it">cappuccino</span> and <span lang="fr">croissant</span> are covered under my <span lang="la">per diem</span> expenses.</p>
Punctuation can also be mis-applied, particularly in image alternative text or hint text, where authors assume every fragment is a full sentence and warrants a period.
<p>This is the best <img src="âŠ" alt="Pie."> I have ever had, and I do not like <img src="âŠ" alt="Peach."> normally.</p>
In that case, even first-time screen reader testers will probably recognize the impact of the two periods.
Added 7 July 2023
I go into more detail in my post Donât Override Screen Reader Pronunciation
.Mis-using aria-roledescription
Every time I see aria-roledescription in the wild, it is to offer hint text. Something like this painfully real example:
<a href="[âŠ]" [âŠ] ariaroledescription="Press enter to activate the menu.">
200
</a>
This developer has effectively told the screen reader that instead of announcing 200, link to replace it and say 200, Press enter to activate the menu.
There is no HTML element by that name. There is no ARIA widget by that name. It is meaningless and hides the control type. Is it a button? A menu bar? A select? A disclosure widget?
For screen readers that correctly (per spec) override the native role with what the developer provides, the user will have little understanding what the control is. The screen reader may still offer its instructions, perhaps as You are currently on a Press enter to activate the menu inside of web content. To activate this, press Control Option Space.
I have put together more reasons why you should be careful using aria-roledescription.
Providing Control Instructions
Many devs think they have to tell screen reader users how a control works, regardless of the fact that using the correct HTML and/or ARIA will allow screen readers to convey that to users.
Besides that being incredibly verbose, it can also be wrong.
<button aria-label="Click button to mark">
[icon]
</button>
Never mind that this overrides the accessible name of the control, this is obviously problematic for a user who does not use a mouse, such as most screen reader users. TalkBack, for example, will tell a user to double-tap to activate when encountering a button.
<a href="[âŠ]">
Services<span class="visually-hidden">, tap to follow</span>
</a>
Even if you go so far as to test for a touch display and think you can offer instructions appropriate for the context, you will still be wrong (patrick_h_lauke). Keyboards paired with mobile phones while running screen readers is incredibly common, so telling the user to tap is contextually wrong. Never mind devices with multiple form factors.
Obviously for custom controls and complex widgets you likely need to offer some basic instructions. Otherwise a screen reader is going to take context into account and provide instructions specific to the platform. It will indicate when the custom accelerator key is needed (JAWS key, Narrator key, VoiceOver key, etc.). It will adapt to a touch screen and tell a user when a tap, swipe, or hardware control is needed. Do not pre-judge what hardware the user has available and can use.
ARIA Authoring Practices
The ARIA Authoring Practices is considered a go-to resource for pre-built accessible patterns. Essentially, a free pattern library for the taking. It is not a standard even though some treat it as one. It is only a note â a bunch of material that may be useful to some authors.
These patterns try very hard to mimic native operating system patterns. However with those efforts they generally do not identify current browser support or bugs (w3c/aria-practices#978), often do not disclose dependencies (w3c/aria-practices#842) clearly, are not mobile-first (w3c/aria-practices#428) (if at all), fail to note the absence of necessary JavaScript events (w3c/aria-practices#8), disagree with published W3C tutorials (w3c/aria-practices#831), and in many cases are not fully tested (w3c/aria-practices#975). There are open issues where users complain (w3c/aria-practices#557) that the recommended patterns are cumbersome (w3c/aria-practices#353) or confusing. These problems result in large platforms encoding (CharlieCroom) confounding interface patterns.
As they are integrated into projects and usability testing is performed, the gaps are becoming more and more apparent. Teams that did not expend the effort to test them are losing their trust in W3C recommendations as a result. I say this with confidence because I am the guy standing in front of rooms of 30 developers at a time on a twice-monthly basis having these conversations.
Info
I have written in more detail on a couple of these patterns:
- Maybe You Donât Need a Date Picker (added 8 February 2024 because APG added a date picker some time ago and I missed it)
Update 20 May 2022: APG Relaunches
On Global Accessibility Awareness Day (GAAD) 2022, the APG relaunched and rebranded itself as an accessible pattern library:
WAI at W3C (x.com/w3c_awi)
Want to use #ARIA to make your web apps more #accessible, yet tired of slogging through a LONG doc? Good news: ARIA Authoring Practices Guide (APG) is redesigned as shorter pages
(related email: lists.w3.org/Archives/Public/public-wai-âŠ) #a11y #ARIAapg #GAAD #WebApps
I am thrilled this no longer looks like a standards doc and is much easier to navigate.
I am less thrilled this left a pile of 404s (w3c/aria-practices) with the move, implies it is a ready-to-use pattern library, obfuscates the (watered down) warnings (w3c/aria-practices#2336) I fought so hard to get added, quietly hid some of its worst patterns with no acknowledgment in years-old issues, appears to have happened outside the W3C redesign project with Studio24, and introduced WCAG issues (w3c/aria-practices#2338).
Update 30 April 2023: APG Adds Support Charts
Despite claims, APGâs support charts are not ARIA support charts and they are not analogous to Can I Use. While brand new and likely to grow, their scope is still strictly APG patterns. I go into more detail in my post No, APGâs Support Charts Are Not âCan I Useâ for ARIA.
I include comparisons with Can I Use and a11ySupport. I also note that APG is still stuck on screen readers only, which means it creates gaps for other assistive technologies and allows WCAG violations.
The Marketing Term âAIâ
Added 8 July 2023. I am going to take the large language model (LLM) popularized by ChatGPT and OpenAI. While marketed as artificial intelligence (AI), this is little more than a dynamic autocomplete designed to sound truthy.
As I have written before, No, âAIâ Will Not Fix Accessibility
.This does not stop companies from marketing fake-AI to solve accessibility problems (with breathless parroting by non-journalists) regardless of hilariously bad outcomes from egregiously inaccessible tools.
Here is UserWayâs output when asked for a text entry field for a numeric 6-digit 2-factor authentication page (this within a code block with aria-hidden="true"):
<label for="otp">Enter the OTP:</label>
<input type="text" id="otp" pattern="[0-9]*" inputmode="numeric" maxlength="6" aria-label="OTP" required>
Or asking for a password field with some standard requirements:
The title attribute provides a description of the password requirements for screen readers.
Or when fed this obviously nonsensical code:
<div role="button" aria-pressed="false" aria-selected="true" type="submit" aria-label="Get started" title="Get started" href="/sign-up">
<span aria-hidden="true">Get started</span>
</div>
UserWay returned this with a false justification for every attribute:
<a role="button" aria-pressed="false" aria-selected="true" aria-label="Get started" title="Get started" href="/sign-up">
Get started
</a>
Granted, expecting fake-AI to create better outcomes for humans is a stretch given the incredibly negative feedback (mdn/yari#9208) MDN has received (mdn/yari#9230) from its two efforts to have fake-AI explain even simple code blocks that themselves are not accessibility issues.
Since LLMs are trained off many of the poor practices I cite throughout this post, LLMs actively regurgitate similar bad advice.
Targeting Code Validation
30 July 2024. Over the years I have encountered developers who rely on validators to control their code quality. The problem is that validators only care about syntax, not how things are exposed to users.
I first wrote about this in 2016 in my post Be Wary of Nesting Roles
. In that post I show nested interactive roles. So a validator would rightly flag this as invalid HTML:<button>
Foo
<button>
Bar
</button>
</button>
But it would at the time allow this:
<div role="button">
Foo
<div role="button">
Bar
</div>
</div>
While the validator closed that gap, there are cases where authors may not agree. If you are using an ARIA role to avoid generating errors with an invalid HTML structure (validator/validator#1432), then it is incumbent on you to test with all the assistive technologies. Especially if you are charged with documenting the scientific record for all of humanity.
Otherwise you cannot act surprised when a screen reader behaves erratically when encountering this untested and invalid structure.
In short, donât do this:
<div role="paragraph">
content starts here
<table>
âŠ
</table>
content goes here
<ul>
âŠ
</ul>
more content here
</div>
All of humanity will find it confounding.
What You Can Do
Sorry, your browser doesnât support embedded videos, but donât worry, you can download it.
Creepy somewhat anthropomorphic robot with a plastic boyâs face says, I am sad, then throws its head back with a childâs laugh and almost no expression change.
I have a couple suggestions.
Test with Users
The bulk of these issues are a function of not knowing how real users actually surf. Developers make assumptions about what will be easier for a screen reader user (or zoom user, or voice user, âŠ) without testing it with screen reader users (or zoom users, or voice users, âŠ).
I cannot teach you how to start testing with users if you never have before. I can, however, direct you to video and slides of my talk Inclusive Usability Testing that covers some of the logistical aspects of incorporating users into your process.
Maybe Code Less
Some developers donât know what these elements, attributes, or features really do, so they end up keeping defaults or adding arbitrary values. Again, without testing with users or assistive technology they have little way of knowing what a mess they have created.
If developers worked to follow the three, no, five Rules of ARIA, much of this might solve itself:
- If you can use a native HTML element or attribute with the semantics and behavior you require already built in, instead of re-purposing an element and adding an ARIA role, state or property to make it accessible, then do so (rule 1 reference).
- Do not change native semantics, unless you really have to (rule 2 reference).
- All interactive ARIA controls must be usable with the keyboard. If you create a widget that a user can click or tap or drag or drop or slide or scroll, a user must also be able to navigate to the widget and perform an equivalent action using the keyboard (rule 3 reference).
- Do not use
role="presentation"oraria-hidden="true"on a focusable element (rule 4 reference). - All interactive elements must have an accessible name (rule 5 reference).
Wrap-up
I will likely add more curious patterns as I find them. If you want to comment with some you have seen, note that I am focused on technically valid code that is unusable and has gotten that way as a result of someone trying to make it more usable or accessible.
Update: 3 February 2022
Eric Eggert talks about the challenges that developers make for disabled users when the developers try to make something âaccessibleâ without any understanding of disabilities or experience with the technology in his post No Accessibility Without Disabilities. As I do, he also cites tables, terrible alternative text, and tabindex everywhere.