Accessibility guidelines
This page provides some general accessibility guidelines. For component specific recommendations, be sure to check out their individual documentation pages.
EUI provides a strong start to building accessibility into your apps. The components provided strive to meet WCAG 2.1 guidelines on semantics, keyboard functionality, color contrast, and so on. How you stitch together these components in the overall page structure also plays a large role in meeting accessibility goals. Headings, landmarks, page titles, focus management, and accessible names all work together to create accessible apps.
Building accessibility into your app is as important as code quality, visual design, and performance, and it’s also important that you test as you go. You can approach accessibility testing from three dimensions: automated, manual, and empathetic thinking. Use automated tests to quickly cover as much ground as possible, manual tests to address more complicated scenarios, and empathy to fill in the gaps.
For a technical intro to accessibility and how EUI tackles it
Headings and landmarks
You can aid navigation and make pages more accessible for screen reader users by using solid headings and landmarks. Headings are the simplest way for screen readers to navigate pages. A good heading hierarchy:
- Uses only one
<h1>
on each page - Doesn't skip levels
<h1> → <h6>
- Doesn't duplicate content
Heading examples
EuiTitle gives you a way to separate your presentation from your semantic markup.
Landmarks are another way for screen readers to navigate pages. A benefit of landmarks is that they offer more context on the type of content to expect than a heading. This is useful for tech that offers reader modes (e.g., Firefox, Safari, and apps like Pocket) and new form factors (e.g., smartwatches). Many landmarks are mapped to HTML elements, such as <main>
, <aside>
, <article>
; others are exposed through the role
attribute.
You can implement named landmarks with aria-label
or aria-labelledby
. However, having a heading inside of the landmark (even if it is visually hidden) and referenced by aria-labelledby
is preferred.
Landmarks example
Headings and named landmarks example
Further reading
Page titles
Each page requires a unique, informative title that accurately reflects what the page does. The best page titles put the unique content first. Effectively, they're reverse-order breadcrumbs.
Use this format: {Unique page title} - {Site title}
Further reading
Focus management
Where is the focus state right now?
Focus states are an important part of design because they let keyboard users know where focus is currently at. All browsers ship with focus states for interactive elements, and most of the time you shouldn’t need to alter these. EUI goes further to customize focus states to match the Elastic brand and provide better visual states, including color contrast.
Where is the focus state going?
Given that a keyboard user primarily navigates pages in one direction (either forward or backward), it’s important to have an intuitive focus order. Focus order should follow the flow of the page to make it easy to follow. If you’ve made a normally non-interactive element like a <div>
interactive via JavaScript, you can enable a tab stop using tabIndex=0
. If you want something that is only focusable programmatically, you can use tabIndex=-1
.
Using tabIndex
values greater than 0 is problematic and should be avoided.
How do I get back to where I was?
Navigating complex sites sometimes means your focus state will jump around (e.g., skip links, modals, typeaheads, and so on). If you remove an element that currently has focus without setting focus anywhere else, users start over at the beginning of the page. Unless there’s a strong reason to do otherwise, focus state should always return to where it was previously if the currently focused element disappears. For example, closing a modal might mean your focus is on a close button; when the modal closes, you should return focus to the button that opened the modal.
Further reading
Disabled elements
Browsers remove disabled elements from the tab order. This means keyboard users cannot tab to those elements or activate nested focus behaviors.
If you disable a button or form element, you need to provide clear instructions to users how to correct errors or remove the disabled state.
When you add the HTML disabled
attribute to an element, you must remove tooltips or other focus interactions. You must also remove focus interactions if you pass the isDisabled
prop to components like EuiAccordion.
Further reading
Naming
An accessible name is the name of an HTML element as it’s exposed to assistive technology. An accessible name can then be read by a screen reader or can be targeted for an action.
Most elements
For most content, the accessible name comes from the element’s inner text, such as: <a href="https://elastic.co">Elastic.co</a>
. A screen reader can now read it out something like “Elastic.co, link” or, using voice commands, it can be controlled with “Click Elastic.co link”.
Images and other elements
Some content might require special attributes to give an element an accessible name. For images, you can use alt
attributes, such as:
<img src="image1.jpg" alt="An apple lays on a table">
Buttons without inner text
For buttons without descriptive text content, you can rely on ARIA to bring meaning back:
<button aria-label="Close modal">X</button>
Forms and more complex patterns
Some HTML elements have associated elements that provide accessible names. Form elements are the most ubiquitous example: a checkbox doesn’t have a name by itself, but when it is associated with a label, assistive technologies can make the connection:
<input type="checkbox" id="subscribe">
<label for="subscribe">Subscribe to Elastic news</label>
Of note: Repeated calls to action
Having only an accessible name, however, doesn’t always lead to the best UX. Take a list of available fields that someone might want to add to their filter (say, on the discovery page of a popular open source project):
<h3>Available fields</h3>
<ul>
<li>
@timestamp
<button>add</button>
</li>
<li>
_id
<button>add</button>
</li>
<li>
_index
<button>add</button>
</li>
</ul>
Here, the 3 buttons have the same accessible name. There are a few different patterns you can use to differentiate between repeated items. For example, each button below shows a possible pattern you can use (in order of recommended best practice):
<h3 id="available">Available fields</h3>
<ul aria-labelledby="available">
<li>
_id
<button aria-label="add _id field to your current filter">
add
</button>
</li>
<!-- The next two options are hardest to make work with Elastic’s i18n framework -->
<li>
@timestamp
<button>
add
<EuiScreenReaderOnly>
@timestamp field to your current filter
</EuiScreenReaderOnly>
</button>
</li>
<li>
<!-- This isn’t recommended but will work in a pinch -->
<span id="filed3">_index</span>
<button id="button3" aria-labelledby="button3 field3">add</button>
</li>
</ul>
<!-- Can be any heading level or even a paragraph -->
<h1 id="a1b2c3">My favorite fruit</h1>
<ul aria-labelledby="a1b2c3"><!-- ... --></ul>
<!-- You can still provide an accessible title even if there's no visual label -->
<ul aria-label="My favorite vegetables">...</ul>
Further reading
Testing considerations
There are a lot of aspects to accessibility, and covering all the bases can be a lot to keep in mind. By relying on standards, you can minimize the amount of special casing you have to do in code, but you should still be cognizant of the many modalities in which users might use your products.
Low-vision
While low-vision users may use many assistive technologies in tandem, this section focuses on zooming. Two ways that users can zoom the page are by increasing the base font-size with browser tools or by using a 3rd-party magnifier (sometimes, a physical magnifier) to better see the screen.
WCAG 1.4.4 defines 200% browser zoom should continue to work with no further action from the user as a Level AA criteria.
ZoomText is the most popular 3rd-party magnifier that gives users a window they can drag over content to magnify and read it out loud. Testing for the best experiences here is exceptionally difficult because you must make visual judgement calls. Specifically, related pieces of information should be close enough together for a low-vision user to efficiently interact with the UI.
Low-vision/blind (screen readers)
Blind and low-vision users often rely on tools, such as screen readers and braille readers, to navigate the web. Screen and braille readers read the page from top to bottom. Building a page with a good structure, will make it quick and easy to navigate. Braille readers are a textual representation of what a screen reader would say so we can focus on screen reader compatibility.
The 3 most common, desktop, screen readers, and their most common browser pairings are:
- JAWS with Chrome
- NVDA with Firefox
- VoiceOver with Safari
Mobile is a little simpler:
VoiceOver for iOS
TalkBack for Android
Learning resources
- A wide-reaching guide on accessibility on MDN covering basics and best practices for a variety of subjects
- The caniuse of ARIA attributes: Accessibility support
- Accessibility web fundamentals by Google, similar in content to the MDN guide, but more guided
- If you prefer videos to reading, a great “pick your subject” style series A11ycasts is available
Practical examples
For many things, there’s no need to reinvent the wheel. If your component is featured in one of these two sources, feel free to borrow heavily!