I have a site that needs to be made fully accessible. We have dynamic content that sits on a single page (doesn't reload) and changes on the screen.
For the screen-reader to keep up with this, I've added some JS logic where the attribute aria-hidden="true"
or aria-live= "polite"
is added to hide and reveal the targeted elements.
Although the element's aria-label
is read out, I run into an issue where the role
attribute is left out.
Situation 1
<div role="button" aria-label="This is a label" aria-hidden="true"></div>
I use JS to remove the attribute aria-hidden
and add aria-live="polite"
when this button needs to be read on the page
Which makes the screen-reader then read "This is a label"
Situation 2
<div role="button" aria-label="This is a label"></div>
However, if the content is read from the get-go without being hidden, ie no aria-hidden="true"
it reads as "This is a label, Button"
I want this behaviour, but with me able to control when this occurs.
I'm using iOS screen reader on the latest Chrome.
I've tried quite a few hacks to get around this:
aria-hidden="true"
to parent and indivdual elements results in role still being omittedaria-live="polite"
to reveal but the opposite aria-hidden="false"
. This however won't even get picked up by the screen-readerAny help or guidance much appreciated.
Additional JSFiddle, with a simplified example (you can use Apple screenreader and click into the window to hear the content read):
All the comments are decent so far but are avoiding the problem. Whether you use a real <button>
or <div role="button">
doesn't matter. Using a <div>
is certainly a lot more work because you need tabindex
and event handlers and aria-label
and such, but if all that is there, it doesn't matter to assistive technology which one you use.
Regarding aria-live
, it's not meant to be a dynamic property. That is, it's not an attribute you want to add on the fly. It works best when the page is loaded and the element already has aria-live
set.
The purpose of aria-live
is to announce changes to the element (or child elements if aria-live
is set on a container). So when the page is loaded and the right elements have aria-live, then anytime you add text to the element (or child element) or add/remove child elements or hide/unhide child elements, those changes will be announced. But only the text is announced. (See aria-relevant
to control what types of changes are announced.)
You can run into timing issues if you dynamically add an element with aria-live
and then add child elements to that new live region. Should the newly added children be announced right then or does the display/refresh cycle need to go through once before the "live-ness" takes affect? It's hard to say because browsers and operating systems combinations work a little differently.
What I have found is that aria-live works fantastic when I'm not dynamically adding that attribute.
Your fiddle example does not work at all with NVDA on a PC. That is, nothing is announced when the new button is revealed, which is what I expect because you're unhiding a button and adding aria-live
to it. So I think the purpose of aria-live
is a little misunderstood. If you add a container around the hidden button and that container has aria-live
, then when the button is unhidden, it'll be announced.
I changed your fiddle to have:
<div aria-live="polite">
<button aria-hidden="true" class="newButton hidden" role="button">
New Content
</button>
</div>
and I changes the JS to remove the aria-live
line
activeButton.addEventListener('click',function testFunc() {
//newButton.setAttribute("aria-live","polite");
newButton.removeAttribute("aria-hidden");
newButton.classList.remove("hidden");
}
Now when I click on the "reveal" button, I hear "new content". I don't hear "button" but that's ok. aria-live
is meant to announce text changes, not the role of elements.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.