Chrome 80/81 Bug: Accessible Name Calculation

The good:
Chrome 80 rolled out on 19 February 2020, and with it came a pile of fixes for how elements with CSS display properties have their semantics exposed in the accessibility tree. These huge accessibility bug fixes featured prominently in my CSUN talk this year (starting at slide 36).

The bad:
Unfortunately, that release introduced a new bug, filed 30 January 2020: Issue 1047549: Incorrect name calculation for ListBoxOption with strong or emphasis text

Add in some of my testing, asking around, wading into a WebAIM thread, and what I found is that some HTML elements nested within <label>s are excluded from the accessibility tree. I am probably over-simplifying, but at the very least it is clear accessible name calculation in Chrome 80 is kinda broken and extends well beyond the listbox scope of the bug report.

The ugly:
The fix came too late to make it into Chrome 81 (per the bug report). With Chrome 81 now delayed, any fix coming in Chrome 82, originally scheduled for 9 June 2020, will come at some yet-to-be-determined future date.

That means this post has a freshness date. After some time in June or July 2020, I hope you can ignore this post.

Example

I discovered this when testing a form on a project. A form I had tested before with a screen reader and which had already been buttoned up and deployed. I made a crude minimal representation of it on Codepen (view it in debug mode to remove Codepen cruft for testing).

See the Pen Testing Chrome 80/81 Bug by Adrian Roselli (@aardrian) on CodePen.

The simplest way to confirm the problem is to open the dev tools and pop into the accessibility inspector. When you look at the accessible name for each control, the text that is wrapped in <strong> and <em> is completely excluded.

Accessibility inspector showing the computed name for the first radio button is “I am infected”, matching its visible text. Accessibility inspector showing the computed name for the second radio button is “I am infected”, not matching its visible text of “I am not infected” where the word “not” is bold. Accessibility inspector showing the computed name for the checkbox is “I affirm my statement above is true”, not matching its visible text of “I affirm my statement above is true and that I waive all HIPAA protections and authorize you to notify my employer” where the second clause is italic.
Screen shots from Chrome 80 dev tools showing the accessible name for each of the two radio buttons and one checkbox.

It may be a bit hard to understand just how much the meaning can be changed by excluding a single word or clause, so I made a video.

Running Chrome 80.0.3987.132 and JAWS 2018 on Windows 10. The first part of the video is me letting JAWS read through the page. The second part of the video (17 seconds on) is me using Tab to interact with the form.

I also confirmed the problem in Chrome for Android.

Text caption from TalkBack with Chrome showing the computed name for the second radio button is “I am infected”, not matching its visible text of “I am not infected” where the word “not” is bold. Text caption from TalkBack with Chrome showing the name for the checkbox is “I affirm my statement above is true”, not matching its visible text of “I affirm my statement above is true and that I waive all HIPAA protections and authorize you to notify my employer” where the second clause is italic.
Screen shots from Chrome 80 on Android 10 showing the caption from TalkBack and demonstrating the bold and italic text are not announced.

On the WebAIM list someone pointed out that a ‘fix’ is to add role="presentation" to each element that is not being announced. Doing so appeared to do the trick. So, yeah, that works, but it is a terrible, awful hack.

Other reports indicate <code>, <b>, and many more on all also have the same problem when part of an accessible name. Which means, essentially, you have to test.

Wrap-up

I don’t know how this happened. I am not dunking on Chrome nor its team. Building a browser with a 6-week life-cycle is hard work. Bugs happen. This just happens to be a bug with potential massive risk for screen reader users.

This is not something an automated accessibility checker would catch. As far as I know, none compares the DOM with the accessibility tree to look for discrepancies. A validator would not catch this, either. This is something you would only catch with manual testing.

Probably do not rush out and add role="presentation" to every inline element that is part of an accessible name. My testing was not that thorough. It would also hobble the experience for browsers that aren’t broken (Firefox). Instead, find those critical forms and screens and spot test them. Then make a decision based on that context and your user stats.

Understand that this bug will be in the wild for at least three more months (late June 2020), perhaps more depending on how far the Chrome 82 release slips. Which you will have to test again.

Update: 1 April 2020

Chrome 82 is being skipped and 83 is being moved up by three weeks, though this appears to be just a naming/semantics issue as it will contain the 82 changes.

The bug report got some traction since I first posted this, and the specific code fix (dated 3 February) is referenced for a merge into the M81 / 4044 branch.

If the updated schedule is accurate, Chrome 81 will drop on 7 April. While I have not heard back on a question about when to expect this, it seems like I should test the release next week if/when it drops.

In the meantime, continue to test your critical applications for the impact of this bug.

Update: 16 April 2020

Good news, everyone! I have updated to Chrome 81 and the accessible name in my examples is no longer broken. If you test my minimal representation of it on Codepen (maybe easier in debug mode) and inspect the accessible name of each control, you will see the text in bold or italics is now represented in the accessible name.

Of course, your users may not have updated. I say this as I wave my hand generally in the direction of a few thousand financial institution employees near my house and who are on machines where Chrome updates are managed via a security policy and will be unable to update immediately.

So still be certain that for now you are not embedding critical information in any additional inline elements when setting an accessible name for a thing.

Update: 21 April 2020

This is not fixed in Chrome 81.

My test case was too limited. While testing another experiment of mine, I discovered that my buttons with text wrapped in <code> were not being used for the accessible name.

I have updated the embedded pen above to contain a <button><code></code></button> construct. You can slice and dice the code as you see fit to test it with other elements, but it is pretty clear this larger accessible name calculation bug persists.

While the bug I cited above was closed as fixed, I opened a new bug to report this: Issue 1073026: Incorrect name for button with text in <code>

Update: 22 April 2020

The bug I filed was merged overnight with Issue 1071827: Accessible name of buttons is not computed correctly when using only css content.

While that issue details a bug in Chrome when using CSS generated content in accessible name calculation, the larger message is that Chrome’s accessible name calculation is regressing and we all need to be diligent about testing.

3 Comments

Reply

In my current code base, I have a badly written button with both strong and b elements contained, that now appears to speak twice in the Chrome 81 beta.

Jonathan Cohn; . Permalink
In response to Jonathan Cohn. Reply

Oh my. Do you have a test case you can add to that open bug? If not, I will see what I can come up with later.

In response to Jonathan Cohn. Reply

A quick check based on what you described shows me that in Chrome Canary (83.0.4102.3) and Chrome Beta (81.0.4044.83) there is no doubling in the accessibility inspector. Nor is there double announcement with JAWS 2018.

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>