Imagine you have a simple, single-page application - regardless of whether it was written using Backbone, Angular, Ember or anything else.
How can you tell a screen reader that we've changed 'page' when a route is followed?
In a classic application, when I navigate from /index.html
to /about.html
the screen reader obviously detects the page change, and re-reads as you'd expect.
In my Backbone application though, when I follow a route I cannot work out how to trigger a 're-read'. I've tried triggering a focus
event which I'd seen somewhere, but that doesn't seem to work.
Note: I'm currently testing with NVDA/Chrome.
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:
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:
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.
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.
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 */
}
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();
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With