Accessibility Best Practices
Foundational WCAG 2.2 Level AA best practices mapped to common HTML elements.
Accessibility best practices refer to a set of guidelines, principles, and techniques that aim to ensure that digital content, products, services, and environments are designed and developed in a way that makes them usable and accessible to as many people as possible, including those with disabilities. These practices are intended to eliminate barriers and provide equal access to information and functionality, regardless of an individual's abilities or disabilities.
Accessibility best practices encompass a wide range of considerations, including web design, user interface design, content creation, software development, and physical spaces. The goal is to create inclusive experiences that accommodate various disabilities, such as visual, auditory, motor, cognitive, and speech impairments.
ARIA
- Identify a live region with an aria-live attribute on a container element.
- The live region must be empty on page load or when it’s first added to the DOM.
- Use aria-live="polite" for most announcement.
- Use aria-live="assertive" when the user needs immediate feedback.
- Use the aria-atomic attribute to specify if the whole live region should be announced, or only the text that changed.
- Use aria-atomic="false" to announced only the updated text.
- Use aria-atomic="true" to announce static and updated text.
- Only use the aria-relevant attribute if the removal of content from a live region needs to be announced.
- Use the aria-busy="true" attribute to notify assistive technology that it should temporarily ignore changes to an element when things are loading. Once everything is in place, clear the attribute or set it to aria-busy="false".
- Use a special type of live region role when appropriate:
- Use role="alert" to announce important and typically time-sensitive information that requires the user’s immediate attention.
- Use role="status" to announce advisory information to the user that is less urgent than an alert.
- Use role="timer" to identify a numerical counter listing the time elapsed from a starting point or the time remaining until an end point.
- Use role="marquee" to define an area as a type of live region with non-essential announcements that change frequently.
- Use role="log" to keep track of sequential updates, such as a chat log, messaging history, game log or an error log.
- Turn off the time limit before encountering it.
- Adjust the time limit before encountering it to a length at least ten times the default setting.
- Extend the time limit. The user must be warned at least 20 seconds before time expires.
- With session timeouts, present warning messages in a popup dialog with options for the user to either extend or end the session.
- For timers with fixed deadlines, provide a countdown feature with ARIA live announcements at strategic intervals.
- When refreshing/reloading a page, ask the user’s permission. Notify users that newer content is available and provide the options to update or continue.
- Use
<!doctype html>and valid HTML5. - Set page language with
<html lang>. - Unique, descriptive
<title>per page. - Logical heading order with a single
<h1>. - Use semantic landmarks.
- Provide skip navigation links.
ARIA live regions:
Time limits:
Any design with a time limit must offer the user the ability to either:
2. Keyboard Navigation & Focus
- All functionality accessible via keyboard.
- Visible focus indicator at all times.
- No keyboard traps.
- Correct focus order.
- Identify important blocks of navigation with the <nav> element or role="navigation" attribute.
- When there are two or more navigation regions on the page, name each with aria-label or aria-labelledby to differentiate them.
- Indicate the current location visually, using CSS, and semantically, using the aria-current="page" attribute.
- Place the skip navigation link at the top of the page before any other focusable element (link, button, or custom control).
- The skip link doesn't not need to be visible until it receives focus.
- Use clear link text – e.g. “Skip to Main Content” or “Skip to Content”
- Use a same-page link, targeting the id attribute value of the destination (usually the <main> element).
- Assign the destination the tabindex="-1" attribute. This fixes shortcomings in some browsers that move the viewport to the destination but not the focus.
- Use CSS to permanently position the link off screen
- Set display: none
- Set visibility: invisible
- Ensure the relative order of components on the page and links within navigation blocks remains unchanged across pages.
- Ensure Table of contents reflects the document's heading hierarchy
- Ensure every topic in the Table of Contents links to the appropriate location
- Ensure a meaningful tab order by positioning focusable content in the same sequence as the underlying code.
- Ensure the keyboard navigation order is logical and intuitive. Typically, this means ensuring the navigation follows the visual flow of the page, left to right, top to bottom. It moves through the banner, main navigation, page navigation and controls, then footer on a typical page.
- Avoid using tabindex values greater than 0.
- If a keyboard shortcut is implemented in content using only letter (including upper- and lower-case letters), punctuation, number, or symbol characters, then at least one of the following is true:
- A mechanism is available to turn the shortcut off.
- A mechanism is available to remap the shortcut to include one or more non-printable keyboard keys (e.g., Ctrl, Alt).
- Active only on focus
- The keyboard shortcut for a user interface component is only active when that component has focus.
- Whenever possible, give the user control over changes of context with an explicit user action that's generally understood to cause a change of context; e.g, clicking a link or pressing a submit button.
- must never be triggered on focus.
- must be anticipated by the user if triggered by changing the setting of a control (on input).
- Consistent navigation
- From one page to the next, the relative order of components on the page and of links within navigation blocks should remain unchanged. Components or links may be removed or inserted, but the relative order should stay the same.
- Consistent identification
- From one page to the next, identical functional components should be consistently named. For instance, a widget named "Search" on one page is named "Search" on the other pages, not sometimes "Find". This includes the alt text of icons and other non-text items with identical functionality.
Skip navigation links:
Do not hide the skip link using any of these CSS options::
Multiple ways:
Table of contents:
Focus and focus order:
Character key shortcuts:
Turn off:
Remap:
Changes of context:
Changes of context::
Consistency:
3. Visual & Color Contrast
- Text contrast ≥ 4.5:1.
- Non-text UI contrast ≥ 3:1.
- No color-only information.
- Zoom support up to 400%.
4. Semantics & ARIA
- Prefer native HTML elements.
- Provide accessible names.
- Synchronize ARIA states.
- Avoid invalid ARIA usage.
5. Forms, Media & Dynamic Content
- All inputs have labels.
- Errors announced to assistive tech.
- Captions and transcripts provided.
- Live regions for updates.
6. Assistive Technology Testing
- Test with screen readers.
- Keyboard-only navigation.
- Zoom and contrast modes.
7. Reporting & Next Steps
| Severity | Description | Action |
|---|---|---|
| High | Blocks access | Fix immediately |
| Medium | Causes confusion | Fix soon |
| Low | Minor issue | Backlog |