question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

aria-live="assertive" blocks label from being read

See original GitHub issue

Issue: If you associate a form label with a react-select input, the label is never announced by a screen reader.

Replication: Example here: https://codesandbox.io/s/n0q28p50xp Tested using react-select v2, VoiceOver and Safari.

Expected behavior: When native select element is associated with a label, a screen reader will read the label when the select receives focus.

Actual behavior: Instead, when the react-select input receives focus, the screen reader is interrupted and begins immediately reading the contents of the A11yText component (which are manually generated by react-select and don’t support including label text) because that component uses aria-live="assertive".

Impact: Without being able to associate a label with the input in a form, this component is not compliant with WCAG 2.0 accessibility guidelines (https://www.w3.org/TR/UNDERSTANDING-WCAG20/minimize-error-cues.html)

Possible solutions include:

  • Using aria-live="polite" instead of "assertive" (better practice, anyway, since you don’t know what else in the application/website the screen reader might be needing to keep track of)
  • Adding a new optional prop where form label text could be passed to the A11yText component
  • Allowing an id prop to be passed to the native input element

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Reactions:6
  • Comments:5

github_iconTop GitHub Comments

2reactions
aferciacommented, Apr 8, 2019

Worth noting the assertive aria-live region can’t be rendered “on the fly”. Instead, it needs to be in the DOM since the beginning and stay there to allow screen readers to “monitor” changes within it.

Especially on Windows, screen readers “buffer” the content of a page. Instead, VoiceOver on macOS has a different behavior. This is very likely the reason why testing on different operating systems with different browser / screen reader combinations highlights inconsistent behaviors in the way the live messages are announced:

  • macOS Safari VoiceOver: I can reproduce what @rheydt reported:
    • focus the input field
    • the aria-live assertive region is rendered in the DOM
    • because of the “assertive” value, the aria-live region content is announced interrupting any other announcement
    • the input role and its label are not announced

This behavior is more similar to the one of an ARIA role="alert" and seems triggered by the way Safari / VoiceOver perceive an aria-live region that is rendered “on the fly” in the DOM. Instead, aria-live regions are supposed to work differently and only changes within their content should be announced.

  • Windows Firefox NVDA: I can reproduce what @zebdelk reported:
    • focus the input field
    • the aria-live assertive region is rendered in the DOM
    • Firefox + NVDA don’t announce the aria-live region content: I guess because they’re not able to perceive a “change” in the aria-live region content simply because the region didn’t exist so there was no live region to “monitor” for changes
    • the input field role and label are announced
    • when selecting the options, only part of the selected option is read out

The last behavior (part of the option is announced) can be explained better with the screenshot below:

Screenshot (195)

When changing the highlighted option from Green to Forest, the part re is ignored because it doesn’t “change”. Both Green and Forest contain re. The part that is perceived as “changed” is announced as Fost.

The two complete strings for the example above are as follows:

option Green focused, 7 of 10. 10 results available. Use Up and Down to choose options, press Enter to select the currently focused option, press Escape to exit the menu, press Tab to select the option and exit the menu.

option Forest focused, 8 of 10. 10 results available. Use Up and Down to choose options, press Enter to select the currently focused option, press Escape to exit the menu, press Tab to select the option and exit the menu.

Please notice that only part of the option name and the option number are announced. All the rest of the string doesn’t change and it’s ignored.

This happens because the aria-relevant and aria-atomic attributes are missing so the default behavior is to announce only the “changed node”. Although it’s not 100% clear to me what a “changed node” is in this context, it’s pretty clear some screen readers announce just part of the string and ignore parts they don’t perceive as “changed” parts. Specifying aria-relevant="additions text" aria-atomic="true" may help.

Additionally (not strictly related;

  • when typing, the message is announced immediately at every keystroke: it would be great if it was debounced while typing
  • when typing and when highlighting an option: the message always includes the instructions: this seems redundant and adds noise to the message: instructions should be announced only the first time users land on the input field.

To recap, there would be the need to improve a few things to make the aria-live region work as expected:

  • the aria-live region should be rendered in the DOM since the beginning
  • important: the aria-live region should not be re-rendered: only its content should change
  • appropriate aria-relevant and aria-atomic values should be used
  • messages should be meaningful and as short as possible

Aria-live regions can be a bit tricky to implement. I’d like to suggest to consider to use the @wordpress/a11y package. It takes care of creating the live regions as soon as the DOM is ready. It takes a string for the message and an optional param for polite / assertive.

Related: #2456

1reaction
ccveercommented, Sep 3, 2019

I want to be able to have a label for a creatable select that is announced properly by the screen reader. I was hoping that the update to the latest react-select with Alison Hall’s PR would fix it, but it doesn’t. I have set inputId to a value and then set htmlFor in my label to that value. I am using a Mac with Chrome with VoiceOver.

It would also be nice if the demo site was accessible. It currently doesn’t have labels for its inputs (it uses headers instead). That way if there is a specific way to associate the label and the input, there would be an example.

Read more comments on GitHub >

github_iconTop Results From Across the Web

ARIA live regions - Accessibility - MDN Web Docs - Mozilla
aria -live="assertive" should only be used for time-sensitive/critical notifications that absolutely require the user's immediate attention.
Read more >
Testing ARIA-LIVE with display:none and innerHTML
Example 4: Test aria-live by turning a child of the container with aria-live=assertive from display:none to block.
Read more >
Aria-Live="Assertive" is not read by JAWS - Stack Overflow
As a quick hack, the following seems to work for me with IE11 + JAWS 15 function ShowTooltip(ttID) { setTimeout(function(){ $('#' + ttID).css('display', ......
Read more >
Using aria-live - bitsofcode
As we saw in my demo above, the assertive value will interrupt whatever task the screen reader user is in the middle of...
Read more >
Hiding and updating content - web.dev
aria -live="assertive" tells assistive technology to interrupt whatever it's doing and alert the user to this change immediately. This is only ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found