Developing reliable, accessible, apps is really a whole-team effort, and something I've not written much about before is how I approach things when I'm not the one writing the code.
This is by no means a complete guide to implementing or testing for accessibility, but hopefully it gives a general idea of things to think about when reviewing a Pull Request 🙂 Feel free to leave any of your own tips, suggestions, or questions in the comments!
If you'd like to skip directly to a section:
- What even is this feature?
- Initial check with axe
- Keyboard operability
- Screen reader checks
- Considerations on focus management and dynamically appearing content
I find it's quite useful to take a step back and consider what UI pattern we're trying to introduce/refactor, and check the WAI ARIA Authoring Practices for a reminder of how that kind of UI pattern should behave.
Those docs are great to bookmark for development too, as they lay out expected behaviours, aria attributes, and link to example implementations.
Stepping back and asking yourself "what is this thing?" also helps spot opportunities to replace
divs with more semantic alternatives. I've lost count of the amount of times I've had a lightbulb moment of "oh wait, this is actually a [insert something that should be obvious here]!".
The axe browser extension helps us capture a lot of low hanging fruit, e.g. colour contrast, missing landmarks or labels.
If there's multiple states the feature can be in, I'd try re-running axe in each state (e.g. a dropdown that's collapsed, vs expanded), as axe can only inspect the current DOM.
NB: If you use a Mac and/or Safari, please make sure your settings allow for tabbing to interactive elements. See Browser Keyboard Navigation in macOS
All features should be operable by keyboard alone, and this includes:
Tabto move through each of the interactive elements in a logical order (e.g. often this would be top-to-bottom, left-to-right)
Shift + Tabto move backwards through those elements
- The currently focused element should be clearly visible (e.g. with a focus outline).
- You should be able to interact with focusable elements as per the conventions in the WAI ARIA Authoring Practices. For example, activating a link with
Enter, moving through combobox suggestions with
Up Arrow/Down Arrow.
- Being able to disclose content that would otherwise be triggered on a mouse hover (e.g. a tooltip that makes helper text appear on hover)
If you ever get stuck debugging invisible focus issues, you can add this in the console to log out the focused element as it changes:
document.addEventListener('focusin', () => console.log(document.activeElement))
I've been asked a few times "Do you always check with a screen reader?" and the honest answer is "No".
My personal view is that a screen reader check is a must when:
- We are introducing a new interactive feature (as opposed to a content change): things dynamically update/appear/disappear
ariaattribute has been changed or introduced: these are only surfaced through assistive technology, so if we're not checking with a screen reader, we're not really checking at all
I usually use VoiceOver and Safari to conduct screen reader checks. This is mostly because VoiceOver is the default Mac screen reader, and is designed to work best with Safari (if you try using it with another browser you'll notice some buggy/unusual things).
If you use a Mac, I have a post with some initial setup instructions:
If you have a keyboard with the function keys in the top row, you can turn VoiceOver on and off with
Cmd + F5.
If you don't have the function keys, you can press the TouchID button three times in quick succession to bring up the accessibility options, where you can check/uncheck 'Enable VoiceOver'.
I usually start a screen reader check using the VoiceOver Rotor (opened with the key combination
ctrl + option + u)- it's an interactive menu that lists different elements by type (e.g. landmarks, links, form controls):
Press the left/right arrow keys to move through the different menus and get a quick overview of the relevant landmarks and accessible names of elements on the page. In the example above, you can quickly spot the 'Home' link has accidentally been named twice!
To jump to a particular element/section, use the up/down arrows to highlight and
Enter to select.
You don't have to use the rotor at all if you don't find it useful, I just prefer it compared to reading through lots of the page to get to the section I'm interested in.
Axe will usually help flag this kind of issue, but as I navigate a feature with a screen reader, I tend to be on the lookout for elements where:
- There is no accessible name (e.g. we've used an icon button with no aria label)
- The accessible name is vague (e.g. 'click here' - to do what?)
- The accessible name is repeated (e.g. lots of "toggle dropdown" - which dropdown?)
It can sometimes be a bit much hearing everything announced as you're navigating around, especially if you're debugging one particular section. You can silence any in-progress VoiceOver announcement by tapping the
ctrl key 🙂
I usually pay particular attention to any features which involve content dynamically appearing/disappearing - for example: a dropdown menu, a warning banner, a modal.
The main things I'd be thinking about for these is:
- How does a low-vision user know that content has appeared/disappeared? Is anything announced via the screen reader?
- If the new content contains any focusable element (e.g. a link) - how do I reach it? If I have to press
Tab20 times something's probably not right.
- If my keyboard focus was inside some content that's now disappeared - where is the focus now?