On this page
- Key Goals
- General Best Practices
- Technical Standards
- Implementation
- Screen reader hinting with WAI-ARIA (or ARIA)
- Dynamic content
- Keyboard Navigation
- Accessible Methods for Hiding Content
- Making content invisible for sighted users only
- Making content invisible, until someone tabs to it
- Completely hide content for all users
- Inline Form Errors
- Related Form Elements
- Using animation responsibly
- Testing Your Work
- Automated Tools
- Nightwatch and Drupal Core
- Keyboard Access
- Testing With Assistive Technology
- Form Accessibility
Accessibility Coding Standards
The Drupal community strives to be inclusive to everyone, including people with disabilities. To that end, the Drupal community has developed the following accessibility coding standards to help make websites and other digital assets accessible to the widest possible audience.
Key Goals
Effective user experiences serve our entire community, including website visitors with disabilities. A positive experience can be achieved by focusing on three goals:
- Creating an inclusive strategy: Consider accessibility needs when architecting the site
- Incorporating Accessible Coding: Use best practices (as outlined below) to ensure that content can be navigated and read by all
- Following Normalized Testing: Building accessibility reviews into existing processes (and not as an add-on) will help to ensure code pushed out is accessible.
General Best Practices
Drupal has made every effort to seamlessly build accessibility in Drupal Core. This process empowers developers and authors to build highly legible content that can be parsed by assistive devices, by:
- Providing text alternatives (alt text) for non-text content, such as images, charts and graphs.
- Providing accurate transcripts, captions, and descriptions for video.
- Ensuring color choices have sufficient contrast to make it easier to read for users with visual impairments.
- Testing to ensure the website is keyboard-navigable, so that users who cannot use a mouse can still access all the content and functionality.
- Using semantic HTML tags, such as
<h1>,<ul>, and<button>rather than<div>,<div>and<div>, to properly structure content and make it understandable to assistive technologies. - Defaulting to using HTML whenever possible and using WAI-ARIA modestly.
- ARIA shims labels for screen readers into non-semantic HTML;
- ARIA versions of elements are generally not as robust, and improper use can either reduce the usability for screen reader users or introduce accessibility errors.
- Checking your work. Never assume something is fine; everybody makes mistakes. Run automated checkers (outlined below), and manually test new interactive components. When possible, invite users with disabilities to test your work.
Technical Standards
Public-facing code integrated into the Drupal CMS, the Drupal.org website or related community sites should strive to meet Web Content Accessibility Guidelines (WCAG) 2.2 AA. Our community strives to keep up with the latest W3C recommendations.
Author-facing interfaces should strive to meet the Authoring Tool Accessibility Guidelines (ATAG) 2.0. ATAG 2.0 is broken into two parts:
- Part A involves accessibility of the authoring tool itself. Authors with disabilities should not face barriers when creating content.
- Part B addresses how that tool supports authors in creating accessible content. Content creation tools should build accessible pages by default through templated widgets, easy-to-use authoring interfaces, and input validation.
The accessibility of the admin side, including the editing tools, should meet the same level of accessibility as the public facing site. Author defaults should also be built to support better accessibility.
Implementation
Screen reader hinting with WAI-ARIA (or ARIA)
WAI-ARIA (Web Accessibility Initiative - Accessible Rich Internet Applications) attributes add semantic meaning to both markup and markup patterns. This semantic meaning cannot be conveyed with HTML alone, e.g.:
- Indicating an accordion toggle is available but currently closed using
aria-expanded="false" - Using
aria-describedby="EXAMPLE-ID"to associate a form field with its help text. - Using
aria-current="page"to indicate which navigation item is active.
When the semantic meaning can be conveyed through HTML, we recommend avoiding using any ARIA attributes.
To add ARIA attributes to elements in Drupal render arrays, use the #attributes property of the #type element in your form definitions. For example, if you have a form field that requires user input, you can add the aria-required attribute to the #attributes property like this:
$form['field_name'] = [
'#type' => 'textfield',
'#title' => t('Field Label'),
'#attributes' => [ 'aria-required' => 'true', ],
];Dynamic content
When content on a page changes following user input, it is important to announce that change to screen reader users with aria-live. Key moments include:
- Alerts and error messages
- When an auto-complete field has provided a possible match
- When an AJAX filter changed the number of search results on the page
To simplify the process, the Community has added the Drupal.announce() function to provide a consistent notification process. The Drupal.announce() function allows JavaScript functions to send a message to a live region on the page, which will be read by screen readers.
To use the Drupal.announce() function, call it with the message that you want to announce as the argument. For example:
Drupal.announce( Drupal.t('Your form has been submitted successfully.') );You can also pass translated strings & change the priority of messages using code like:
Drupal.announce( Drupal.t('This is important!'), 'assertive' );When assertive is indicated, the screen reader will interrupt other aural text with the message.
Keyboard Navigation
Any feature that can be operated using a mouse must also work using a keyboard. Default HTML elements provide this functionality when used as intended. When implementing custom elements, be sure to test that a user can tab into and out of the element, click using keyboard or space bar, and use additional expected keys as outlined in the ARIA Patterns guide.
Certain widgets, such as popover dialogs, should capture and trap keyboard focus in the same manner that they overlay content for the mouse. Focus must then be released when the user clicks a “close” button or presses the Esc key. To assist with this process, Drupal Core includes a "tabbingManager" JavaScript class, which include methods to constrain and release focus as appropriate. You can invoke constrained tabbing with the Drupal.tabbingManager JavaScript feature:
var tabbingContext = Drupal.tabbingManager.constrain( $('.contextual-toolbar-tab, .contextual') );A set of encoded elements is passed to using the constrain method. Pressing the tabbing key will now only move between the tab-enabled elements.
To remove the tabbing constraint, the release method must be called on the tabbing context object.
tabbingContext.release();More information can be found with the Drupal 8 release of the tabbing constraint feature.
Accessible Methods for Hiding Content
Making content invisible for sighted users only
Drupal provides a CSS class, "visually-hidden," which can be used to hide content visually, but leave it available to screen readers. Common uses include providing alternative text for an icon provided as a background image, or to provide visually hidden headings to label navigation regions.
Please be mindful that not all screen reader users are unable to see the content; some use it for “read along” functionality to assist with low vision or cognitive disabilities. If the visual and non-visual experiences are drastically different, visually hiding content may reduce the quality of the user experience by creating confusion.
Making content invisible, until someone tabs to it
Use Drupal's "visually-hidden" CSS class together with the CSS class "focusable" on an element to ensure that when a keyboard user focuses it, it becomes visible. Sighted keyboard users typically use the skip links feature.
Completely hide content for all users
Drupal’s CSS class “hidden” was created based on best practices to hide content from both sighted users and from screen readers. This class could be used instead of the general CSS instruction “display: none;” on an element.
More specific instructions on hiding content can be found in the documentation.
Inline Form Errors
Drupal's inline form errors module highlights errors next to the input field, rather than at the top of the page. Highlighting errors near the field makes it easier for users to locate and correct their errors. This feature is available in Core, but it is not enabled by default. Developers should manually enable this module and test that their code works as planned.
Testing form errors, while often overlooked, is nonetheless a crucial step in the development process, especially when coding for audiences with disabilities. Make sure the error explains how to correct the input, e.g.:
- "Quantity must be greater than 0" rather than "Invalid quantity," or
- "Password must contain at least 8 letters" rather than "Password is too short"
Also make sure the error is announced by screen readers if it is inserted as a link to the dynamic content above.
See more information below about testing form accessibility.
Related Form Elements
When form inputs are visually grouped, use a <fieldset> with a <legend> element to make that grouping machine-readable. Grouping checkboxes with appropriate legend elements allows screen reader users the ability to know which box they are checking.
Radios, checkboxes, Form API, and the advanced search all utilize fieldsets by default.
Using animation responsibly
Animation is cool. It can help people know where to focus. It can also make people physically ill. Before adding animation, please consider how it will improve the users experience before doing so. If animation is enabled, make sure that user preferences are respected. The following is a best practice for adding animations responsibly.
For Drupal, we are recommending that people put any animation into a prefers-reduced-motion media query that is explicitly set for no-preference. Clearly isolating the animations builds on our accessibility defaults:
@media (prefers-reduced-motion: no-preference) {
/* styles to apply if a user's device is not set to reduce motion */
}
If you are building an module or theme that is heavy with animation, it may be more practical to call out which animations you can disable, but at the moment, code on Drupal.org generally has minimal animation.
@media (prefers-reduced-motion: reduce) {