Tell screen reader that page has changed in Backbone/Angular single-page app Tell screen reader that page has changed in Backbone/Angular single-page app angularjs angularjs

Tell screen reader that page has changed in Backbone/Angular single-page app


Overall, you should not need to trigger a 're-read', and depending on your UI that might not be a good thing anyway.

My experience has been with angular.js (as an accessibility person rather than the developer), and our overall approach was to manage the focus rather than trigger a re-read. (We do extensive accessibility testing.)

The key thing from a UI point of view (primarily for screen reader users) is that selecting a link (e.g. about.html) should take you somewhere.

In this case the appropriate place to put the focus would be the top of the content area of the about 'page', hopefully an <h1>.

In order for that to work the target element should be focusable via a script, so probably needs tabindex unless it is a link or form control:

<h1 id="test" tabindex="-1">

The -1 means it is not in the default tab order, but is focusable via a script. See more at WAI-ARIA authoring practices.

Then at the end of the function that loads the new content, including the tabindex attribute, add something like:

$('#test').attr('tabindex', '-1').css('outline', 'none');$('#test').focus();

When adding tabindex dynamically it is best to do so in a line before the focus() function otherwise it may not work (I remember that from testing with JAWS).

To test this I would use either:

  • NVDA & Firefox, Windows
  • Jaws & IE, Windows

It is also good to test with VoiceOver on Safari/OSX, but that works differently and may not hit the same issues as a windows based screen reader.

You will hit a lot of issues with Chrome/NVDA as that is not supported very well, and end-users are very unlikely to use that. IE is ok with NVDA, but Firefox is best.

Overall, it is worth getting to know the WAI-ARIA authoring practices, particularly Using ARIA in HTML. Even though you are using a JS app, the browser (and therefore screen reader) is interpreting the resulting HTML so that advice is still relevant.

Lastly, if you are updating page content without the user pressing space/enter to activate something, you might find that JAWS/NVDA do not know about the new content as their 'virtual buffer' has not updated. In that case, you might need to add a JS shim to make them update, but only do that if you run into problems in testing, it should not be a global patch.


Taking the answer from @AlastairC, and the comments below it. I've taken this a bit further now and am going with this as my solution going forward:


My go-forward solution

I found that just reading out the first heading wasn't really that useful. Especially if the last page you were on was a loading sequence. You can hear that there something new has been focused, but it's certainly not clear that this forms the part of a whole now page.

Add some useful, descriptive text to the page

As such I now have a single paragraph at the top of my page layout template. This includes a screen-reader friendly message, along with a very rough overview of what the page.

<p class="screenreader-summary" tabindex="-1">  The <strong>Dashboard</strong> page is now on-screen.  It contains several widgets for summarizing your data.</p>

Note that the tabindex value allows us to focus this element with JavaScript. You might not want to use a p element for this, you can use anything you like really.

Hide it off-screen (optional, only required if it would break your design/readability)

This is then coupled with CSS to move this element off-screen:

.screenreader-summary {  position: absolute;  left:-10000px;  top:auto;  width:1px;  height:1px;  overflow:hidden;  outline: none; /* Important, don't show an outline on-focus */}

Focus this element, when a new page is shown on-screen

Finally, in the JavaScript code that shows your page on screen (e.g. in MarionetteJS using onShow or the show event):

$yourViewEl.find('.screenreader-summary').focus();

The result

I'm a sighted person, so take what I say with a pinch of salt - however I found that reading out a short description is so much more useful.


For angular the url changes, If someone REALLY needs to reread everything, (like me because of requirements), what did the trick for us was this:

$(window).on('hashchange', function () {    location.reload();});

and we just added extra code to handle pages like "success" were no reloads are supposed to happen.this simulates the actual page loading, and screen readers will read it normally like a page change.kind of defeats the purpose of angular in a way, but this will help people like me who already have the application, and want a quick fix.