Accessibility
Core principles
There a myriad of websites offering advice on making accessible web apps and even some tools that can automatically tell if a web app is WCAG compliant. This document is to not go into too much detail, instead explain the main principles to creating an accessible web app, what tools to use to automate checks and what we need to think about that aren’t captured by automated tools.
An accessible web app is more than making a document that is readable for screen readers to assist people with sight disabilities, it is making the entire web app operable with keyboard controls for those with muscular and motor neuron issues. It is also about making content simple and easy enough to understand for people with learning difficulties and honouring operating system settings to stop animations for those who suffer from motion sickness
If you are already using the react component library a lot of this is already handled.
Semantic markup
Document structure and using the correct HTML elements is the most important aspect of web accessibly. We only use extra tools like ARIA attributes as a band aid when we cannot use standard semantic mark up.
Good document structure involves having defined <header>
, <main>
and <footer>
sections, having an <h1>
on every page only having <h2>
s under an <h1>
and only having <h3>
s under <h2>
s and only having <h4>
s under <h3>
s and so on and so forth.
For more information about good document structure see this reference:
https://developer.mozilla.org/en-US/docs/Learn/Accessibility/HTML
For information on ARIA attributes see this reference:
https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA
Using the correct HTML5 elements is very import too. For example, using <nav>
to wrap nav links and <form>
wrapping the contents of a form and wrapping form inputs with labels and legends where possible. If there is a list of items, make that obvious by placing the list items in <li>
s and wrapping them in a list element <ul>
or <ol>
.
If an item is a button, a <button>
element is better than <a role=”button”>
, which is better than <div role=”button”>
. They might look the same to the human eye if they are styled in the same way, but screen readers read and navigate these elements differently. In fact, people who use screen readers often navigate web pages in a non-linear way. There are often tools to list headings and all available links and allow the user to jump directly to those links.
There are more benefits to using declarative mark up, when using elements like <button>
, keyboard navigation works out of the box. It will not for <div role=”button”>
which would need to be changed to <div role=”button” tabindex="0">
.
There are many HTML5 elements, and it is always worth checking to see if there more suitable elements that might better describe page content:
https://developer.mozilla.org/en-US/docs/Web/HTML/Element
For a full list of WCAG guidelines see this reference, please note that these standards evolve over time and will change:
https://www.w3.org/TR/2021/WD-wcag-3.0-requirements-20210121/
Keyboard navigation
Even though we can write some tests that use keyboard navigation the only way to make sure that keyboard navigation behaves as expected is to manually test it. Buttons, links, and form inputs will work with tab navigation, for any other element setting a tab index is required. The tab index should ideally always be set to 0, this will allow the browser to handle the tab index order. This order will not necessarily match the order of how the CSS makes elements appear on the screen but follow the order of the elements in the underlying HTML document.
When an item is in focus, it needs to be clearly identifiable, there is no point keyboard navigation if the focus is not visible. The current design system suggests that browser defaults should be used for focus outlines.
If you have collapsible menus, the contents of the menu when collapsed should be skipped over by visibility: hidden; or display: none;
Macs by default have a setting at operating system level that prevents keyboard navigation working with anchor tags, Chrome ignores this but Safari and Firefox honours this setting. There is an article explaining how to fix this here: https://www.scottohara.me/blog/2014/10/03/link-tabbing-firefox-osx.html
Motion sickness
Operating systems can have a setting that can indicate to the browser to limit animations for people that suffer from motion sickness.
To honour this setting the react component library uses a small bit of CSS in the global style component to stop all transitions, smooth scrolling behaviour and pauses all animations at the end of the animation like this:
@media (prefers-reduced-motion: reduce) {
*,
*:after,
*:before {
animation-play-state: paused !important;
animation-direction: reverse !important;
transition: none !important;
scroll-behavior: auto !important;
}
}
Testing
To test accessibility a multifaceted approach is needed because automated tests that scanning for accessibility issues will only capture ~30% of what is required. We also need to think about keyboard navigation and to physically test the webapp with a screen reader.
Automated testing
Anything that uses axe-core which uses a rule set based on WCAG guidelines with some additions will suffice. There is no preference it depends on your project which is more appropriate however Jest is likely to be faster than Cypress.
https://www.npmjs.com/package/cypress-axe
https://www.npmjs.com/package/jest-axe
Test accessibility by default
Another way to make sure that an app is accessible is by writing tests that navigating content and interacting with controls in components, whilst avoiding the use classes and IDs. If navigating the page is possible using only predictable elements, text, labels, legends, and aria-labels, this is effectively navigating around the app in an analogous way to a screen reader. If this is not possible then this is a good indication that the app most probably is not accessible.
It is also advices to move around elements especially forms, not only selecting them by text or label but by emulating keyboard navigation with use of the tab key.
Testing with screen readers
We can observe how a screen reader might interpret page content by using dedicated software or the built-in screen reader that might come with the operating system.
Using voice over on mac
For macs command + f5
toggles the voice over.
Useful commands:
tab
: Move through interactive elementsenter
: Select elementup arrow
anddown arrow
: Interact with optionscontrol + option + a
: Read out screencontrol + option + u
: Navigate by content Heading, Link etc
Using voice over on windows
For windows there is the build in Narrator Windows key + Ctrl + Enter
but has limited features. When testing on a Win laptop it is better to test with NVDA which is free to download.