Accessible Description Exposure

If you have little experience with ARIA, screen readers, or testing in general, understanding accessible descriptions can be trickier than understanding accessible names (already confusing for many). I have written explanations so many times for clients and in fora that I opted to put this together so I maybe never have to explain it again.

Background

First it’s important to know how an accessible description is computed. The Accessible Name and Description Computation specification handles this, specifically referencing aria-describedby, and then deferring to the other features such as title (in very limited circumstances) and <desc> (for SVGs). In the future, aria-description may exist and be supported as well.

Next we need to understand where we can assign this description. The ARIA 1.3 draft helpfully tells us which roles cannot be assigned an accessible name through ARIA, which also applies to accessible descriptions. For example, the generic role is one of them. The generic role maps to <div> and <span>, meaning you cannot assign an aria-describedby to either element (nor an aria-label or aria-labelledby) unless it has an appropriate role.

Finally, to test how this is all exposed to users you need to fire up screen readers. Then you need to pair those screen readers with browsers, ideally using pairings that match what your audience uses. After that, you will need to navigate the page all the different ways users can. This includes understanding screen reader interaction modes, how desktop screen readers and mobile screen readers have different behaviors, and then considering getting some Braille display expertise involved.

Results

While this post is about how and where the accessible description is exposed by assorted screen readers, it has the added benefit of showing you where and how the accessible name is exposed as well. Lucky you.

My test case only looked at a button and a link. Nothing more complex. They both use the same description text, referenced by aria-describedby.

For the scope of this recap, the term “accName” means accessible name and “accDesc” means accessible description. I wrap the auto-generated text from the screen reader as sample output (the <samp> element). Since this post is about accessible descriptions, I also wrap accDesc in <strong> so it is distinct from the accessible name.

For Windows users, Caps Lock is the laptop JAWS key and NVDA key. On macOS, Ctrl + Option combined are the VoiceOver key. Bear this in mind when reading official documentation that references JAWS, NVDA, or VO keys because you will not find those on your keyboard.

Outdoor metal tactile map / sculpture of a fortress with a Braille explainer set in front of it.
Kraków’s Barbican as represented in a tactile model and Braille description (English and Polish). Built in 1489, it is the site of where, in 1768, haberdasher Marcin Oracewicz held off invading Russian forces. Supposedly he fashioned a brass button from his clothes into a bullet and killed the tsar’s general. Other information for blind and partially-sighted visitors to Kraków’s heritage sites is available in a 2012 presentation.

Desktop screen readers, with no Braille display:

Mobile screen readers, with and without paired keyboard:

Overall, TalkBack exposes the accessible description the most while JAWS does the least. When VoiceOver on iPadOS and NVDA each expose the accessible description, they do so consistently for links and buttons in the same navigation context.

Keep reading for the test case and videos of screen readers handling it.

Interesting note is that all screen readers announce the link and the button the same when you set focus with script as if you had tabbed to it. Except VoiceOver on iDevices. This may be due to heuristics and may behave differently in your project.

Test

View (and fork) the test page on Codepen, or hit the debug view for proper testing.

See the Pen aria-describedby Demo by Adrian Roselli (@aardrian) on CodePen.

The relevant code:

<button type="button" aria-describedby="Desc">Drink me</button>

<p>
<a href="…" aria-describedby="Desc">Follow me</a>
</p>

<p>
Shared description:
<span id="Desc">This is the description for this thing you are on.</span>
</p>

Screen Reader Output

The following sections are videos from assorted popular screen reader and browser pairings. They do not use hot keys (like pressing B to jump to a button) because I forgot them in my first draft.

JAWS

JAWS 2021.2107.12, Chrome 99.
JAWS buttons list JAWS links list
Neither the buttons nor links list in JAWS exposes the accessible description.

NVDA

NVDA 2021.3.1, Firefox 98.
NVDA buttons list NVDA links list
Neither the buttons nor links list in NVDA exposes the accessible description.

Narrator

Narrator, Windows 10, Edge 99.
Narrator buttons list Narrator links list
Neither the buttons nor links list in Narrator exposes the accessible description.

VoiceOver on macOS

VoiceOver, macOS 12.1, Safari 15.2.
VoiceOver buttons list VoiceOver links list
Neither the buttons nor links list in VoiceOver exposes the accessible description.

Orca

Orca 3.36.2, Firefox 99, Ubuntu 20.04.4 LTS.
Orca buttons list. Orca links list.
Neither the buttons nor links list in Orca exposes the accessible description.

ChromeVox

ChromeVox with Chrome on ChromeOS 100.0.4896.93. Note this is not the ChromeVox plug-in you can get for Chrome on other platforms.
ChromeVox buttons list. ChromeVox links list.
Both the buttons (form elements) and links list in ChromeVox expose the accessible description. This is the only screen reader in this collection that does so.

TalkBack

TalkBack 9.1, Chrome 98. There is an audio track, but no sound. Since Google first acknowledged the issue last year of Android’s failure to capture TalkBack with its on-screen recording feature, it has regressed. On Google’s flagship Pixel 6, the on-board mic seems to cancel out TalkBack announcesments and the touch indicator feature has been removed.

VoiceOver on iPadOS

VoiceOver, iPadOS 15.1, Safari 15.2.

Verdict

Definitely do not rely on the accessible description to convey critical information (such as instructions). Definitely do test it in more than browser dev tools, screen reader logs, and scripted screen reader tools.

This post took a really long time to put together — testing, recording, captioning, clipping, writing up, documenting, re-testing, tweaking, rambling, and so on. If you use this in your job, maybe convince your employer to contract me for some project work. Or maybe buy me a sandwich.

Steve Faulkner has documented how aria-label and aria-labelledby are supported:

Scott O’Hara has written on aria-describedby as well:

Update: 6 April 2022

Added Orca test results performed by eurodiverse.

Update: 16 April 2022

Added test results for when focus is set to the control via script.

Update: 17 April 2022

Made and added video for Orca tests.

Update: 18 April 2022

Added test results and video for ChromeVox on ChromeOS, with thanks to Scott Vinkle for the materials.

11 Comments

Reply

Thanks for this write up Adrian. I recently came to this same verdict a few weeks ago when I considered using aria-describedby on some toggle buttons, but my own testing with NVDA and JAWS got the same results you did, and the information was important enough that I decided to add it to the accessible name instead. I didn’t even bother testing with Talkback since I knew it wasn’t going to fly, but I kind of wish I would have since it apparently passes with flying colors (what a pleasant surprise that would have been).

Bruce B; . Permalink
Reply

hey Adrian,
Are you familiar with the following issue related to aria-describedby:

Windows Chrome (only, currently using v99), an active element () with aria-describedby properly associated. If the text that aria-describedby is associated with changes, when NVDA or JAWS are running, that changed text is announced almost as if a live region existed?

Mark

In response to mark. Reply

Hi Mark! I am indeed aware of that. Scott O’Hara reported it just over three years ago on Chrome 73: Issue 946653: Content added to an aria-describedby element is treated as a live region

It was closed almost two months ago as WontFix, with the note works as intended.

Reply

textarea element…

In response to mark. Reply

I may be misunderstanding what you are asking, but I will try to address it by adding detail to what I said above that I should not have excluded.

  1. The Chrome team closed the issue because Chrome is behaving per the spec. The Core AAM 1.2 specification section 4.8.1 State and Property Change Events lists aria-describedby as one of the properties that should fire a change event if its value is updated.
  2. This should apply to <textarea> elements as well.
  3. Per the links above, the macOS AX API does not seem to mandate a change event (it is listed as TBD.
Reply

Thanks Adrian, learned something new this week. Hope things are going well?
Mark

In response to mark. Reply

Yay! I was useful to someone! And things are well enough that I could track down that info without any angry calls.

Reply

Many thanks for that great report!

Reply

Thanks for doing the legwork on this. One additional thing of note is that I believe most SRs will announce the description if the control is focused via Javascript, similar to the way they behave for tabbing. I’ve found this useful when focusing fields that have inline error messages.

In response to James C. Reply

James, this post is meant to reduce the speculation I see many devs (and testers) use to make a decision when a simple test could demonstrate the results. As such I updated the test to include buttons to set focus to both of the sample controls.

Fun fact — they all announce the control as if the user had tabbed to it, except VoiceOver on iDevice. VO does not announce the accessible description for either, and it does not announce the control type for the button. This may be a function of heuristics or it may be a hard rule. No idea without making more tests.

Thanks for the suggestion!

Leave a Comment or Response

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>