Heading
- List item 1
- List item 2
- List item 3
The aim of this documentation is to help developers to understand how to implement accessibility guidelines.
E.g. If the element acts like a button, use a <button>
, if it is navigation, use <nav>
Ensure all elements pass at least WCAG AA
Ensure that headings (<h1>
to <h6>
) are in the correct order with no skips
Using aria states and properties can provide extra information to users
At the very basic level, ensure that pressing tab allows focus on elements that require it. All functionality shoud be accessible without using the mouse
Make sure images have alternative text if they need it, leave the alternate text blank if they do not
Ensure the code scales well if the user were to zoom in, or set they browser to increase the font size
Uses tools such as WAVE Web Accessibility Evaluation Tool to check for any errors with your code
Use a screen reader to ensure the code makes sense to users who don't browse the site visually
Using the correct HTML markup will often result in the desired accessibility behaviour. This can save a lot of time and effort.
For example, compare how a screen reader interprets the following elements, visually they are identical, but semantically the first example is easier to navigate when using a keyboard, and provides a more detailed read-out in a screen reader.
The role
attribute can be added to an element to help screen readers understand its function. In general it is preferable to use standard HTML elements which natively have their role, rather than adding a role to an element.
There are a variety of resources online which list the available role
s, so here is a curated list of some of the roles we have found most useful:
role="alert"
- Typically used to notify a user of a change on the website. Screen readers will automatically detect a change in content and read it out.role="application"
- Tells screen readers that the element and all its children should be treated as a desktop application. Using this role will stop the element from reacting to key presses in the standard way, so will require custom JavaScript to enable keyboard navigation. role="button"
- Makes the element clickable, often needed if the element has a JavaAscript click event attached to it. In general, using a <button></button>
would be preferable.role="combobox"
- A widget that contains a text input which reveals a list of results based on the entered text. Requires a role="listbox"
child element, which has multiple role="option"
child elements.role="dialog"
- Signifies that the content is a sub-window and should be treated separately from the rest of the page.role="listbox"
- Used in conjunction with role="combobox"
. This is the list that contains the selectable options.role="option"
- Used in conjunction with role="listbox"
. This is an option in the list.role="region"
- An area of the page which contains a group of similar elements.role="status"
- A region that contains advisory information, but is not important enough to justify using role="alert"
.role="tab"
- An individual tab in a role="tablist"
which opens a role="tabpanel"
.role="tablist"
- A list of role="tab"
which open role="tabpanel"
.role="tabpanel"
- An panel in a role="tablist"
which is opened when a role="tab"
is selected.role="tooltip"
- A popup that is revealed to show information about an element.States and properties fulfil similar roles as they detail information about a particular element. Properties (such as aria-label
) are unlikely to change, while states (such as aria-busy
) will often change and describe the current status of the element.
States and properties are vital to screen readers as it helps them offer information about the element that would otherwise only be apparent to users visually inspecting the website.
There are a variety of resources online which list the available aria states and properties, so here is a curated list of some of the states and properties we have found most useful:
aria-activedescendant
- Contains the ID of the currently active child element, for example the currently selected item in a combo box.aria-autocomplete
- Indicates whether a text input can trigger autocomplete suggestions.aria-busy
- Indicates that something is happening in/to the element and for the screen reader to wait before alerting the user.aria-controls
- A list of ids of elements controlled by the current element.aria-current
- Indicates the the element is the current item.aria-describedby
- Contains the id of an element that describes the current element.aria-disabled
- Indicates that the element cannot be interacted with.aria-expanded
- Indicated if the element is expanded or collapsed.aria-hidden
- Indicates whether the element is visible to the screen reader. This can allow the element to be visible on screen, but ignored by the screen reader.aria-invalid
- Indicates whether the entered value is valid on form elements.aria-label
- A value that labels the current element.aria-labelledby
- Contains the id of an element that labels the current element.aria-live
- Indicates that the element will be updated and how the screen reader should notify the user.aria-modal
- Indicates that this element is a modal.aria-pressed
- Indicates whether the current element (usually a button) is pressed.aria-required
- Indicates that the current element is required.aria-sort
- Indicates the current sort order.Unfortunately, like browsers, screen readers come with their own unique set of quirks.
There is not a set standard on how screen readers should convey marup, so keep in mind that something that reads in the desired way in one screen reader, my not read the same way in another. For example, focus on the following link in Chrome using NVDA, and then using Windows Narrator:
NVDA will read:
Aria label text visited link Title text
Windows Narrator will read:
link Aria label text
Windows Narrator omits the title text, so if this text was crucial to the user understanding the context of the link you would need to find another way of communicating this information.
Testing a screen reader in one browser unfortunately isn't enough as using the same screen reader in different browser can lead to different read outs. For example, listen to how NVDA reads out the following list in Chrome/Edge and Firefox:
Chrome will read:
list with 8 items Qualification BA (Hons) Duration 4 years Study mode Full-time Start date 2016 out of list
Firefox will read:
list with 8 items Qualification BA (Hons) blank Duration 4 years blank Study mode Full-time blank Start date 2016 out of list
Notice the additional "blank" that is read out in Firefox.
Using tab to cycle through focusable elements is only one way of navigating websites using a keyboard. Each screen reader has their own methods, shortcuts and key combinations to allow navigation of websites.
tabindex
tabindex
is extremely important to anyone with sight impairment.
It allows easy and predictable keyboard navigation of all page elements that one would normally interact with using a pointing device.
By default the browser works out the logical order of all the keyboard focusable elements on the page, based on source order. You should only modify this native behaviour when absolutely necessary and adhere to the following rules.
tabindex
Doing so creates an artificial order for keyboard navigation. Subsequently, the source order could be different to the tab order. This can be confusing if you are relying on a screen reader and keyboard to navigate the page as the page would not follow a logical tab order.
tabindex="0"
to enable keyboard focusing on elements not natively focusablee.g. span
, div
, p
. Any element with tabindex="0"
will have its tab order dictated by the logical order of the markup and therefore be focusable via the keyboard in a logical, predictable way. In general, if you are adding tabindex="0"
to make an element focusable, you should consider using a more suitable element for the task e.g. button
, a
, input
tabindex="-1"
to change focus programmaticallyAdding tabindex="-1"
will stop users from being able to tab to the element while still allowing it to be focussed programmatically (i.e. by JavaScript). This can be useful when an item needs the focus set on them but should not be tabbed to via the keyboard. For example, you may want to set the focus on a modal that has just openned without letting the user focus on it when using the keyboard.
The following is the suggested pattern for displaying tabs.
Key | Action |
---|---|
tab ⇥ |
|
shift ⇧ + tab ⇥ |
|
Home | Focuses on the first tab and activates it. |
End | Focuses on the last tab and activates it. |
left ← |
|
right → |
|
The following is the suggested pattern for displaying comboboxes.
Key | Action |
---|---|
tab ⇥ |
|
shift ⇧ + tab ⇥ |
|
Esc | Closes the combobox suggestions if it is open. |
Enter | Selects an option when it is highlighted. |
right → |
|
up ↑ |
|
down ↓ |
|
right → |
|