Accessibility Tips For Web Development
8 min read
One of my knowledge gaps within web development that I really want to bridge is accessibility. In all of the apps / engineering teams I’ve worked on professionally to date, accessibility (unfortunately) has never played a front and centre stage, and tends to be more of an afterthought. This is mostly due to time and resource constraints, but also a lack of knowledge on how to implement accessible apps and the benefits it brings.
To start making steps to improve my knowledge, I recently decided to take an online course on accessibility for web development. Here are my quick notes and key takeaways, written in a cheat sheet format (mostly for me to reference back to at a later date!). If you’re knowledgeable about accessible web development, and think I’ve missed something crucial out, please do let me know, and I’ll add it to the list.
Screen readers
- Add alt text to images, otherwise screen readers will end up reading the filename.
- Empty strings as alt tags will cause the screen reader to skip over the image (which may be the desired effect you want, e.g. for user uploaded images or decorative images).
- For complex images, you could make the image hidden to screen readers, but add some text below, that’s visually hidden, but readable by screen readers.
- If you have a video, add captions. At WCAG2 Level A, you can include this as a transcript. To improve on this, use synchronised captions.
- Screen readers ignore CSS background images.
Accessible HTML
- Use appropriate semantic markup. Some have no special functionality, but others do, like
button
,input
andtextarea
.- e.g. if you just use
div
, this would not be read by a screen reader.
- e.g. if you just use
- Don’t choose which header tags to use based on formatting! e.g. there should only be one
h1
tag per page. - Ensure that the reading and navigation order (determined by code order) is logical (so it makes sense when read by a screen reader from top to bottom).
- Use form field labels, so that form inputs can be read by screen readers. Labels can be used explicitly (use
for
to link it to a particular input name) or implicitly (wraps the name and input field - does not needfor
attribute). - The
label
tag only works with certain elements (e.g.input
,button
).- If you need to label an element that’s not “label-able”, use
aria-label
attribute instead (however note that it would only work on focusable elements, so would also require atabindex
attribute).
- If you need to label an element that’s not “label-able”, use
- Use a specific class to visually hide an element that’s solely for screen reader only content.
.visuallyhidden { position: absolute; left: 0; top: -500px; width: 1px; height: 1px; overflow: hidden; }
- If you choose not to use the
button
element, and instead to use adiv
styled as a button, you’d also need to include the following attributes to make it accessible:onclick=”xxx”
role=”button”
(this is the ARIA role, used by screen readers)tabindex=”0”
(or whatever number, to make it tab-able and focusable with the keyboard)onkeyup=”xxx”
(to ensure keyboard-only users can interact with the button)
ARIA - Accessible Rich Internet Applications
- Labels
aria-label
- inline attributearia-labelledby
- allows you to link to an element id that contains the text for the label e.g. could be handy for handling translationsaria-describedby
- provides extended information the user might need
- Roles can be applied to any element. Role examples include button, checkbox, tree, banner.
- States and properties inform what the current state of an element / app is in e.g. is a checkbox checked, or is a form invalid? These would need to be added and removed in line with the user action.
- You can use ARIA properties within CSS since they are just data selectors.
- The ARIA spec allows us to mark an element as containing live data so that screen readers can read out live updates as they come.
assertive
means interrupt,polite
announces the update when the screen reader is next idle.off
will not read the update.- This kicks in whenever the content between the div tag changes.
<div aria-live="assertive">Waiting for a ride</div>
Focus management
- Keyboard shortcuts - allow users to access different features through using the keyboard alone.
- Keyboard only users - show focus rings around elements which are also safe for screen readers. Should be able to reach the next focusable element by tabbing.
- Also should not result in a substantial change in the page layout e.g. page shifts because of the focus ring designs.
- Skip links help users skip over large headers and navigation, to go straight to the main content of the site (without having to tab through each link).
- Create an anchor within the body and add it to the start of your HTML content. Make it visually hidden, until someone hits tab (and make it immediately in focus).
- The anchor should then link to the main content.
- Accessible tab navigation allows a user to navigate to the next tabbable item.
Shift + tab
allows a user to navigate back.- Tabbable elements out of the box include:
a
,button
,input
,select
,textarea
,iframe
- Tabbable elements out of the box include:
- Use a
tabindex
attribute to make any element tabbable- A negative value means it should be focusable, but not reachable via sequential keyboard navigation.
0
means the element should be focusable and reachable, but its relative order is defined by the platform convention.- A positive value means it should be focusable and reachable. Its relative order is defined by the value of the attribute. The higher the value, the earlier it’s reached.
- Note, top level elements should be tabbable, but child elements should be arrow-key reachable e.g. if you have a tab navigation, with “more” as one of the tabs, the child links within “more” should not be accessed via the tab key, but arrow keys.
- You can get the DOM’s current active element by using
document.activeElement
. This is useful to store the currently focused element before a page transition so you can return the user to it later. - Tab trapping is a JS technique where you grab the first and last element in a modal, and listen to keydown events for when the user is on the first/last element. You can then ensure that the tab and shift+tab takes the user through a loop of the tabbable elements in the modal (otherwise the user might tab out of the modal to the main document, even whilst the modal is open).
Visual considerations
- Use this website to check colour contrast: https://webaim.org/resources/contrastchecker/
- Lighthouse audit (Chrome extension) can also check your live site.
- Chrome devtools’s colour picker shows the contrast ratio of two colours, however, this only works if you’ve set the child within a parent component (rather than against the document body).
- You shouldn’t just rely on colour to relay feedback back to the user (e.g. with form validation). There should also be some other method of feedback, like text.
- Consider using NoCoffee for Firefox to simulate what visual impairment views might look like.
- Consider keeping related items (especially those that provide feedback to user interactions) close together to help users with limited field of vision.
- Set the
lang
attribute (the language of your site) at the top of your HTML file (and any subsequent sections where the language deviates from the default). - Even though it might not be visually apparent, WCAG also specifies you should ensure your HTML is free of syntax and parsing errors.
- Users can set a “prefers reduced motion” option on their operating system. This is important for users who may suffer from seizures.
- This is accessible within CSS via an
@media (prefers-reduced-motion)
query.
- This is accessible within CSS via an
- Users can also set their system’s preferred colour scheme (i.e. light vs dark colour scheme).
- This is accessible within CSS via an
@media (prefers-color-scheme)
query.
- This is accessible within CSS via an
Tooling
- Use an IDE linter on your code base e.g. eslint-plugin-a11y
- Use an accessible design system, e.g. from Adobe React Spectrum, Bootstrap, Google’s Material Design
- Developer tools from Deque: https://www.deque.com/axe/devtools/
- Lighthouse: https://developers.google.com/web/tools/lighthouse