Frontend Accessibility Compliance
What is Accessibility (a11y)?
Accessibility refers to designing and developing websites, applications, and tools in a way that they can be used by everyone, including people with disabilities. This includes considerations for users with visual, auditory, motor, or cognitive impairments.
a11y is a numeronym for "accessibility". The number 11 represents the 11 letters between the first letter "a" and the last letter "y" in the word "accessibility."
Why is Accessibility Important?
- Ensures inclusivity for all users.
- Improves usability for everyone, not just users with disabilities.
- Often required by laws and regulations (e.g., WCAG, ADA, Section 508).
Key Aspects of Accessibility (a11y):
- Perceivable: Content must be presented in ways users can perceive (e.g., text alternatives for images).
- Operable: Users must be able to interact with the interface (e.g., keyboard navigation).
- Understandable: Content and interface must be easy to understand.
- Robust: Content must work across various devices, browsers, and assistive technologies.
Standards and Guidelines:
- WCAG (Web Content Accessibility Guidelines): A set of guidelines for making web content accessible.
- ARIA (Accessible Rich Internet Applications): Attributes to enhance accessibility for dynamic content and user interface components.
To implement WCAG (Web Content Accessibility Guidelines) principles (POUR) and ARIA (Accessible Rich Internet Applications) in an Angular application, you can follow these best practices:
WCAG Principles (POUR) in Angular
The correct pronunciation of WCAG is typically "W-C-A-G", where each letter is pronounced individually: "double-u see ay gee". However, some people pronounce it as "wi-kag" or "double-yu-kag", but the most widely accepted pronunciation is spelling out the letters: "W-C-A-G".
1. Perceivable
- Ensure that content is presented in ways that users can perceive.
Implementation in Angular:
-
Text Alternatives for Images: Use the
altattribute for images.<img src="logo.png" alt="Company Logo"> -
ARIA Roles and Labels: Use ARIA attributes to provide additional context for screen readers.
<button aria-label="Submit Form">Submit</button> -
Angular Material Accessibility: Angular Material components are designed with accessibility in mind.
<mat-form-field>
<mat-label>Username</mat-label>
<input matInput placeholder="Enter your username">
</mat-form-field> -
Color Contrast: Ensure sufficient contrast between text and background colors. Use tools like Contrast Checker to verify.
2. Operable
- Ensure that users can interact with the interface using a keyboard or other assistive technologies.
Implementation in Angular:
-
Keyboard Navigation: Ensure all interactive elements are focusable and navigable using the
tabkey.<button tabindex="0">Click Me</button> -
Focus Management: Use Angular's
Renderer2or@angular/cdk/a11yto manage focus dynamically.import { FocusMonitor } from '@angular/cdk/a11y';
constructor(private focusMonitor: FocusMonitor) {}
ngAfterViewInit() {
this.focusMonitor.focusVia(this.buttonElement, 'keyboard');
} -
Skip Links: Provide a "Skip to Content" link for keyboard users.
<a href="#main-content" class="skip-link">Skip to Content</a>
<div id="main-content">
<!-- Main content here -->
</div> -
Avoid Time Limits: Avoid or provide options to extend time limits for user interactions.
3. Understandable
- Ensure that the interface is easy to understand and operate.
Implementation in Angular:
-
Form Validation with Clear Error Messages: Use Angular's reactive forms and provide descriptive error messages.
<form [formGroup]="form">
<input formControlName="email" placeholder="Email">
<div *ngIf="form.get('email')?.invalid && form.get('email')?.touched">
<p>Email is required and must be valid.</p>
</div>
</form> -
Consistent Navigation: Use Angular's
RouterModuleto maintain consistent navigation patterns.const routes: Routes = [
{ path: 'home', component: HomeComponent },
{ path: 'about', component: AboutComponent },
]; -
Readable Content: Use simple language and avoid jargon. Provide tooltips or help text where necessary.
<button matTooltip="Click to submit the form">Submit</button>
4. Robust
- Ensure that the application works well across different browsers, devices, and assistive technologies.
Implementation in Angular:
-
Semantic HTML: Use semantic HTML elements to ensure compatibility with assistive technologies.
<header>
<h1>Welcome to Our Website</h1>
</header> -
Responsive Design: Use Angular's
@angular/flex-layoutor CSS media queries to ensure responsiveness.<div fxLayout="row" fxLayoutAlign="center center">
<div fxFlex="50%">Content</div>
</div> -
Testing with Assistive Technologies: Test your application with screen readers (e.g., NVDA, JAWS) and browser accessibility tools.
-
Use ARIA Attributes: Ensure compatibility with assistive technologies by using ARIA attributes where necessary.
<div role="alert" aria-live="polite">Form submitted successfully!</div>
ARIA (Accessible Rich Internet Applications) in Angular
Common ARIA Attributes:
-
aria-label: Provides a label for an element.<button aria-label="Close">X</button> -
aria-labelledby: Links an element to another element that provides its label.<div id="dialog-title">Dialog Title</div>
<div role="dialog" aria-labelledby="dialog-title">
Dialog content here.
</div> -
aria-live: Announces dynamic content changes to screen readers.<div role="alert" aria-live="polite">Your changes have been saved.</div> -
role: Defines the role of an element (e.g.,button,alert,dialog).<div role="dialog">This is a dialog</div> -
aria-hidden: Hides elements from assistive technologies.<div aria-hidden="true">This content is hidden</div>
Tools for Accessibility in Angular:
-
Angular CDK Accessibility: Use the
@angular/cdk/a11ypackage for managing focus, keyboard shortcuts, and more.import { FocusMonitor } from '@angular/cdk/a11y'; -
Linting for Accessibility: Use tools like
eslint-plugin-jsx-a11yoraxeto identify accessibility issues. -
Accessibility Testing Tools:
- Lighthouse (built into Chrome DevTools)
- axe DevTools
- NVDA (screen reader)
- WAVE (Web Accessibility Evaluation Tool)
By following these guidelines and leveraging Angular's built-in tools and libraries, you can ensure your application adheres to WCAG's POUR principles and provides an accessible experience for all users.
Property Binding
you were introduced to Property Binding - a key Angular feature that allows you to bind element properties to dynamic values.
For example, <img [src]="someSrc"> binds the src property of the underlying HTMLImageElement DOM object to the value stored in someSrc.
Whilst it might look like you're binding the src attribute of the <img> tag, you're actually NOT doing that. Instead, property binding really targets the underlying DOM object property (in this case a property that's also called src) and binds that.
This might look like a subtle detail (and often it indeed doesn't matter) but it's important to understand this difference between element attributes and property. This article can help with understanding this difference.
Whilst it won't make a difference in Angular apps in many cases, it DOES matter if you're trying to set attributes on elements dynamically. Attributes which don't have an equally-named underlying property.
For example, when binding ARIA attributes, you can't target an underlying DOM object property.
Since "Property Binding" wants to target properties (and not attributes), that can be a problem. That's why Angular offers a slight variation of the "Property Binding" syntax that does allow you to bind attributes to dynamic values.
It looks like this:
<div
role="progressbar"
[attr.aria-valuenow]="currentVal"
[attr.aria-valuemax]="maxVal">...</div>
By adding attr in front of the attribute name you want to bind dynamically, you're "telling" Angular that it shouldn't try to find a property with the specified name but instead bind the respective attribute - in the example above, the aria-valuenow and aria-valuemax attributes would be bound dynamically.