Building Accessible Single Page Apps

The Issue
As JavaScript frameworks and libraries to build single page apps (SPAs) proliferate and become more ubiquitous, a new host of web accessibility concerns are created that must be addressed. Specifically:
- Asynchronous rendering of content can be difficult for screen readers to accurately interpret
- Library specific components and modules may not meet accessibility best practices
- Library specific focus based event handlers that can interfere with keyboard accessibility
This article does not aim to provide a primer to web accessibility, and assumes some knowledge of both accessibility and web development. If you’re just getting started with web accessibility, some wonderful introductory resources are available through the W3C and WebAIM. I’d also recommend checking out Marcy Sutton’s article Accessibility is a Civil Right to get an understanding of the importance of developing accessible sites and applications.
I approach this from the perspective of having just re-written my personal site using the React library, so examples will be somewhat specific to this, but the principles should be more broadly applicable.
Asynchronous Content Rendering
The goal of a single page app is just that: render different areas of content or functionality asynchronously within the context of a single page. While there are a lot of reasons this is preferable from a technical standpoint (performance, ease of development, etc) this can potentially introduce issues for users accessing your app via screen reader.
Traditionally, a screen reader would begin reading the DOM from the top to bottom each time the page reloaded. By refreshing the content asynchronously, there is some ambiguity around whether to start re-reading the DOM, and the point from which the screen reader ought to begin reading. While I’m certain that screen reader technology will evolve to accommodate this ever more popular application architecture, there are steps we as developers can take today to ensure these users have a positive experience.
Use of the ARIA live region helps the screen readers to understand that the content labeled as such ought to be have priority to the users. If you’ve not used this ARIA attribute previously, it essentially designates a level of priority for a given DOM node to the screen reader, allowing it to understand whether it falls into one of three categories:
aria-live=”off”
Setting in which the region will not signal to screen readers that any sort of priority be assigned to the DOM node
aria-live=”polite”
Setting in which the region will signal to screen readers that priority should be applied to this DOM node, and that the user should be notified of the updated content once any current actions are completed. Far and away the most common designation.
aria-live=”assertive”
Setting in which the region will signal to the screen reader that the highest level of priority be assigned to the DOM node. This will interrupt any current user action with the content. This would likely only be appropriate for notifications such as user errors which require immediate correction to proceed.
By setting the ARIA live region attribute to polite for each main content component or module, you help the screen reader to know that the content has been updated and make the user aware of the location of the content selected via navigation.
Components and Modules Not Adhering to Accessibility Best Practices
As the JavaScript ecosystem quickly grows and evolves, so too do the number of components for each library and framework that aim to enable quick and efficient development in your library or framework of choice.
The example I ran across when re-writing my personal site in React was the use of icon fonts. While there can certainly be some arguments made for using SVG rather than icon fonts, they seemed a good choice for my particular project, so I set out to utilize font awesome for my project. Having utilized the font library extensively in the past, I am very familiar with the default implementation via fonts & CSS/LESS/SASS. However, there are a number of React components that seek to optimize the implementation of the library for a React stack. These tout improved performance and reduced page weight, and can be called in your components with a little snippet of JSX.
The trouble I ran into was that unlike the typical HTML markup used to render my icons, these were less easily customized to include attributes like ARIA hidden to improve my markup. You may also want the ability to include a title or alt attribute. In the end I decided to go with the standard implementation to be able to have more control over the markup.
This is just one example, but the principle remains the same: the plethora of components and plug-ins available may or may not be optimized for or built with accessibility in mind. As a developer, it’s your responsibility to be cognizant of this, and make informed choices that balance accessibility with all other development considerations.
Focus Event Handlers
The libraries and frameworks that we utilize to build SPAs can be opinionated about navigation in particular. As part of the framework facilitating the navigation between the components that comprise our application, they often implement conventions that can manipulate or interfere with the default browser implementation of focus.
The impact of this can be detrimental to users with mobility impairments, in particular those who access the app solely through keyboard navigation. For these users, the order and visibility of keyboard focus is critical being able to efficiently navigate your app.
It’s important to understand how this works within your application. Try to access all functionality in your application without using your mouse to understand the areas in need of improvement. Heydon Pickering made a great suggestion in his Sitepoint article Learning to focus() that developers should grep their codebase for the focus() method to understand what, if any, changes have been made to how focus is handled in the application. This will provide you with a good starting point for identifying any accessibility issues that need to be remedied.
End Game
These are just a few accessibility concerns to keep in mind while building SPAs that I came across during a very small scale project undertaken to learn React better. As you work with SPAs, be cognizant of accessibility issues that may arise within this particular architecture, and document your fixes. Share them with the development community; as developers, we have an obligation to wield these libraries and frameworks responsibly to ensure everyone can use the apps we build.