Is it possible to make a screen reader reread the select element if the contents of the aria-label changes?
I've made a simple snippet, I know I'm not following most aria conventions, to show what I mean.
If you turn on a screen reader and click on the div it will read the label "unchecked" if you then press space the label will update but the screen reader will stay silent. Though it will read the new label if you click off and on again.
Is this the right way to make the screen reader read updates or is there another method I'm not aware of?
let toggleSwitch = document.querySelector('.toggle-switch');
toggleSwitch.addEventListener("keyup", function(e) {
let code = (e.keyCode ? e.keyCode : e.which);
if (code == 32) {
let nextState = toggleSwitch.getAttribute('aria-label') == 'unchecked' ? 'checked' : 'unchecked';
toggleSwitch.setAttribute('aria-label', nextState);
}
})
.toggle-switch {
width: 50px;
height: 50px;
}
.toggle-switch[aria-label="unchecked"] {
background: red;
}
.toggle-switch[aria-label="checked"] {
background: green;
}
Press space to change state
<div class="toggle-switch" tabindex="0" aria-label="unchecked"></div>
Is it possible to make a screen reader reread the select element if the contents of the aria-label changes?
I've made a simple snippet, I know I'm not following most aria conventions, to show what I mean.
If you turn on a screen reader and click on the div it will read the label "unchecked" if you then press space the label will update but the screen reader will stay silent. Though it will read the new label if you click off and on again.
Is this the right way to make the screen reader read updates or is there another method I'm not aware of?
let toggleSwitch = document.querySelector('.toggle-switch');
toggleSwitch.addEventListener("keyup", function(e) {
let code = (e.keyCode ? e.keyCode : e.which);
if (code == 32) {
let nextState = toggleSwitch.getAttribute('aria-label') == 'unchecked' ? 'checked' : 'unchecked';
toggleSwitch.setAttribute('aria-label', nextState);
}
})
.toggle-switch {
width: 50px;
height: 50px;
}
.toggle-switch[aria-label="unchecked"] {
background: red;
}
.toggle-switch[aria-label="checked"] {
background: green;
}
Press space to change state
<div class="toggle-switch" tabindex="0" aria-label="unchecked"></div>
Thanks for your help.
Share Improve this question asked Feb 2, 2018 at 16:29 Andrew BoneAndrew Bone 7,2912 gold badges20 silver badges34 bronze badges2 Answers
Reset to default 16I currently work in web accessibility. Your element does not need to read the update on the fly to be compliant with WCAG2.0 (AA), as long as the correct state is being read to the user when they navigate back to the element, that's fine!
However, if you do want it to read out the state of the div after the user activates it with space or enter, I'd probably suggest creating a screen reader only div and include aria-live="polite"
, then inject your changed state into that.
Typically you'd create a screen reader only class with something along the lines of this:
.sr-only {
position: absolute;
left:-99999px;
height: 1px;
width: 1px;
overflow: hidden;
}
Aria-live will alert the user to any text updates in this "live" region as they occur, so when a user activates your div, update the sr-only with your new state (and I'd continue to update your aria-label as well so it's read out correctly if a user navigates away from the element and returns later).
Note: This won't work with your label, labels are generally only read when a user navigates to an element, so even if you just tacked aria-live onto your existing div it's not going to re-read the label to the user when updated :)
EDIT: See the fiddle below for a working example. I only have voiceover on this machine but it's quite simple and I'm fairly certain it will work with JAWS and NVDA as well.
https://jsfiddle.net/jafarian/8hck0o3m/
More info
https://www.w3.org/TR/wai-aria-1.1/#aria-live
Use these patterns to have screen readers conveniently read out the state of the control on each interaction (no JavaScript required whatsoever):
<button aria-pressed="false">Mute Audio</button>
or
<input id="my-a11y-button" type="checkbox" aria-checked="false">
<label for="my-a11y-button">Mute Audio</label>
What the example in the OP's question tries to implement is effectively a Toggle Button. The W3C has recommendations specifically for this use case: https://www.w3.org/WAI/ARIA/apg/patterns/button/
Also, generally it's good to avoid implementing accessible elements as pure <div>
s, b/c for screen readers a <div>
is just a logical design container that most implementation will completely ignore, even if it has aria-*
attributes.