I have a scenario where I have added an aria-label
to a parent <div>
which contains some text. Ideally the aria-label
provided to the parent <div>
should be narrated first and then the child Text component. This works completely fine on MacOS Chrome with the VoiceOver screen reader, but on Windows Chrome with NVDA the parent <div>
aria-label
is not at all read.
Attaching a code snippet for reference:
<div aria-label="Parent div accessibility">
<Text> Some Text </Text>
</div>
Speech output on MacOS Chrome with VoiceOver:
Narrator - Parent div accessibility
Narrator - Some Text
Speech output on Windows Chrome with NVDA:
Narrator - Some Text
Screen readers are all over the map with respect to interpretting aria-label
on non-interactive elements.
According to David MacDonald's tests, VoiceOver and TalkBack will read the aria-label
text on static elements, but JAWS and NVDA will not unless the static content (like a <div>
) has the role="navigation"
, role="search"
, role="main"
, or role="img"
.
By design, aria-label
is meant to override the existing text of an element because it is what most screen readers will interpret as the element's label. So, the behaviour you're getting from VoiceOver is not necessarily standard behaviour. Some screen readers (like TalkBack) will ignore the inner text of your <div>
if you use aria-label
, because it interprets the aria-label
as the label for that element and ignores any other text within the element. Other screen readers like JAWS will read both the aria-label
text and the inner text of the <div>
if you add a role like role="navigation"
to your static element. It seems that NVDA 2018 did support using aria-label
on static elements, but it was later removed because there's yet to be consensus on the aria-label
debate.
The fail-safe option would be to use text that is visibly hidden by CSS. This is fully supported by all browser/screen reader combinations.
Here is the example suggested by WebAIM:
<style>
.sr-only {
position:absolute;
left:-10000px;
top:auto;
width:1px;
height:1px;
overflow:hidden;
}
</style>
<div class="sr-only">This text is hidden.</div>
Another option is to use the CSS content
property to hide the text that you want spoken by the screen reader, as suggested by slugolicious in a similar question on SO:
<style>
div::before {content: "This text is hidden"; font-size: 0px;}
</style>
I tested his suggestion with JAWS and NVDA and it announced the "This text is hidden" text as well as the inner text of the <div>
.
However, as QuentinC pointed out in the comments, the CSS content
property isn't currently supported by all browser/screen reader combinations.
For reference:
Clarify use of aria-label on elements with no role #756
Woe-ARIA: The Surprisingly but Ridiculously Complicated World of aria-label/ledby
What happens with aria-labelledby, aria-label and aria-describedby on static HTML elements?
WebAIM: Invisible Content Just for Screen Reader Users
I edited my original answer to include QuentinC's suggestion of using CSS to hide the text.