javascripthtmlwai-ariascreen-readers

Making a screen reader reread if the aria-label changes


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.


Solution

  • I 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