Photo of new Smashing Book 6 titled "Frontiers in Web Design"

Accessibility Tips in Single-Page Applications

I recently authored a chapter on Accessibility in Single-Page Applications in the new Smashing Book 6, New Frontiers in Web Design. In the chapter, I wrote about the unique characteristics of accessibility in web applications rendered with client-side JavaScript frameworks and libraries, such as React, Vue, Angular, Ember, and so-on. I covered focus management, properly disabling backgrounds, and handling asynchronous form updates in a screen-reader accessible way. I also included a bulleted list at the end with relevant and easy-to-digest accessibility tips.

Of course, now that my chapter has been printed into a gorgeous hard-cover book with embossed gold metallic flourishes, I have a few things I wish I could add; particularly to the short list of tips.

To capture a more complete picture of accessibility in single-page apps still in a concise format, I’ll start with the “accessibility rules” listed in the book chapter and add a few extras that are still on my mind now that it’s been published. Each one of these could probably consist of its own blog post, but the intent of this one is to highlight tips and techniques that could help in your next JavaScript-focused project.

  1. It’s easier and less costly to incorporate accessibility the earlier you tackle it, starting with UX and Design.
  2. Prototype complex or custom interactions early, and include accessibility.
  3. Check out the ARIA Authoring Practices for known interaction patterns.
  4. Be generous with color contrast; it not only both helps people with low vision and color deficiency, but also low-contrast projectors and outdoor displays.
  5. Screen readers have ways of navigating other than using the TAB key, so you don’t need to make everything focusable.
  6. Interactive widgets (i.e. “controls”) should be designed to work with the keyboard, not just on hover or swipe.
  7. Get comfortable with focus management in JavaScript, and write it into your automated tests.
  8. Test with accessibility browser extensions and automated testing tools for extra muscle. (Deque’s axe and WorldSpace Attest tools fall into this category)
  9. Test your app with real users, including users with disabilities. Organizations like Knowbility’s Access Works can help.

And now for the additional stuff:

  1. Accessibility is about more than developing for users with blindness or low-vision. Familiarize yourself with the needs of people with disabilities with help from the W3C.
  2. Consider whether a single-page app is really necessary, and if you even need to use a JavaScript framework at all.
  3. If you do go the single-page app route, ensure your core user paths actually work without JavaScript turned on, using server-side pre-rendering. This also helps with SEO!
  4. Make sure that client-side view changes are known to screen reader users by announcing the change in page title, using ARIA live regions and/or focus management.
  5. Semantic structure is more important than developer ergonomics. Craft the most semantic HTML pages you can, regardless of your CSS or JavaScript development tools.

Without these accessibility rules applied, JavaScript-heavy web applications can leave users with disabilities behind. It’s unfortunate how few good examples there are of client-rendered applications like these, but with the right knowledge and best practices we can put much better accessibility examples out into the world.

For more information on developing accessible web applications with JavaScript, check out our training materials on or a number of talks and articles from me (Marcy Sutton). If you have any questions about how to apply these principles or would like to schedule a pairing session, don’t hesitate to reach out to us on Twitter or email.

update selasa

Comments 2 responses

  1. Hello Marcy,

    Great article. Can you explain more about single page application behavior when it comes to focus management. In many applications we have seen when route changes to different view the SR does not start reading the page from top, is it necessary to put a manual focus on heading1 or SR users knows how to navigate If the title was read different but SR did not start reading automatically from top of the page on route change?

  2. Hi Meghna,

    There are multiple techniques that could be used for client-side view changes; which one is best for users depends on the semantic structure and UX of your application. Focus management is one technique of moving focus when content changes. It has multiple purposes: to announce new content upon focus, and to get keyboard and screen reader users’ focus point into the changed part of the view so they can more easily navigate. I’ve seen it done with both headings & wrapper elements with tabindex="-1", and keyboard-interactive elements like buttons. Sending focus to a wrapper element with tabindex="-1" when they click a nav link will read that subview’s content aloud, as opposed to a single heading…there are pros and cons to both approaches. Usually we don’t attempt to mimic the exact screen reader behavior of a hard browser refresh when doing client-side view changes, because it would require setting focus to the body element and making keyboard & screen reader users start over from the top of the page (not the best user experience).

    I’ve seen some AT bugs where focused view content isn’t read aloud because the screen reader doesn’t recognize DOM content changes–one workaround is to send focus to a keyboard-interactive element, like a link or button. Any such bugs with AT should be filed with the vendor, though, so we can eventually avoid workarounds.

    Another technique is to use an ARIA Live Region to announce a changed page title or content, often leaving the user’s focus on the same nav item they activated…but whether this is better for users is debatable. I’m interested in doing some user testing with these various techniques to see which experiences are more ergonomic and intuitive.

Leave a Reply

Your email address will not be published. Required fields are marked *