Skip to main content

Overview

Accessibility is a core principle of Angular Material. All components are designed to work with assistive technologies and follow WAI-ARIA best practices to ensure your applications are usable by everyone.
Angular Material components are tested with screen readers and keyboard navigation to ensure they provide an accessible experience out of the box.

Browser and Screen Reader Support

Angular Material supports the most recent two versions of all major browsers:

Desktop Browsers

  • Chrome
  • Firefox
  • Safari
  • Edge

Mobile Browsers

  • Chrome on Android
  • Safari on iOS

Screen Reader Support

Angular Material aims for great user experience with the following screen readers:
NVDA and JAWS with Firefox or Chrome
  • Use NVDA (free) or JAWS for testing
  • Test with both Firefox and Chrome
  • Verify keyboard navigation works correctly
  • Check that ARIA labels are announced properly

Accessibility Features

Keyboard Navigation

All Angular Material components support full keyboard navigation:
  • Tab: Move focus forward
  • Shift + Tab: Move focus backward
  • Components maintain proper tab order
  • Focus indicators are clearly visible
Many components support arrow keys:
  • Menus: Up/Down arrows to navigate items
  • Tabs: Left/Right arrows to switch tabs
  • Lists: Up/Down arrows to navigate options
  • Date Pickers: Arrow keys to navigate calendar
  • Enter: Activate buttons and links
  • Space: Toggle checkboxes and select options
  • Escape: Close dialogs and overlays
  • Home/End: Navigate to first/last items

ARIA Support

Angular Material components implement appropriate ARIA attributes:
Components provide accessible labels:
<!-- Automatic labeling -->
<mat-checkbox>Accept terms</mat-checkbox>

<!-- Manual aria-label -->
<button mat-icon-button aria-label="Close dialog">
  <mat-icon>close</mat-icon>
</button>

<!-- aria-labelledby -->
<div id="dialog-title">Confirm Action</div>
<div role="dialog" aria-labelledby="dialog-title">
  <!-- content -->
</div>

Focus Management

The CDK provides powerful focus management tools:
1

Focus Trap

Trap focus within dialogs and overlays:
<div cdkTrapFocus>
  <!-- Focus cannot leave this region with Tab key -->
  <button>First</button>
  <button>Second</button>
  <button>Third</button>
</div>
2

Focus Monitor

Track how elements receive focus:
import { FocusMonitor } from '@angular/cdk/a11y';

constructor(private focusMonitor: FocusMonitor, private el: ElementRef) {}

ngOnInit() {
  this.focusMonitor.monitor(this.el.nativeElement).subscribe(origin => {
    console.log('Focused via:', origin); // 'mouse', 'keyboard', 'touch', 'program'
  });
}
3

Initial Focus

Set initial focus in regions:
<div cdkTrapFocus>
  <input cdkFocusInitial placeholder="This receives focus first">
  <button>Submit</button>
</div>

High Contrast Mode

Angular Material supports high contrast modes used by users with low vision:
@use '@angular/cdk';

.my-button {
  @include cdk.high-contrast {
    outline: solid 1px; // Adds border in high contrast mode
  }
}

.my-card {
  @include cdk.high-contrast($target: active) {
    border: 2px solid;
  }
}

Strong Focus Indicators

Enable enhanced focus indicators to meet accessibility requirements like WCAG 2.4.7:
theme.scss
@use '@angular/material' as mat;

html {
  @include mat.theme((
    color: mat.$violet-palette,
    typography: Roboto,
    density: 0
  ));
  
  // Enable strong focus indicators
  @include mat.strong-focus-indicators();
}

Customize Focus Indicators

@include mat.strong-focus-indicators((
  border-color: red,
  border-style: dotted,
  border-width: 4px,
  border-radius: 2px,
));

Accessibility Best Practices

Every interactive element needs an accessible label:
<!-- Good: Has visible label -->
<mat-checkbox>Accept terms and conditions</mat-checkbox>

<!-- Good: Has aria-label -->
<button mat-icon-button aria-label="Delete item">
  <mat-icon>delete</mat-icon>
</button>

<!-- Bad: No label -->
<button mat-icon-button>
  <mat-icon>delete</mat-icon>
</button>
Use the correct HTML element for the job:
<!-- Good: Button for actions -->
<button mat-button (click)="save()">Save</button>

<!-- Good: Link for navigation -->
<a mat-button routerLink="/home">Home</a>

<!-- Bad: Div as button -->
<div (click)="save()">Save</div>
Use headings in order (h1, h2, h3…):
<!-- Good -->
<h1>Page Title</h1>
<h2>Section Title</h2>
<h3>Subsection</h3>

<!-- Bad: Skipping levels -->
<h1>Page Title</h1>
<h4>Section Title</h4>
Make errors accessible to screen readers:
<mat-form-field>
  <mat-label>Email</mat-label>
  <input matInput [formControl]="email">
  <mat-error *ngIf="email.hasError('required')">
    Email is required
  </mat-error>
  <mat-error *ngIf="email.hasError('email')">
    Please enter a valid email
  </mat-error>
</mat-form-field>
Text should have sufficient contrast ratio:
  • Normal text: At least 4.5:1
  • Large text (18pt+): At least 3:1
  • UI components: At least 3:1
Use Material Design colors which are designed for sufficient contrast.
Test your application using only the keyboard:
  • All interactive elements are reachable
  • Focus indicators are clearly visible
  • Logical tab order is maintained
  • No keyboard traps exist
Screen readers may read capitalized text character-by-character:
<!-- Bad -->
<button>CLICK HERE</button>

<!-- Good -->
<button>Click here</button>

<!-- Good: CSS transformation if needed -->
<button style="text-transform: uppercase">Click here</button>
Images and icons need alternatives:
<!-- Decorative icon (hidden from screen readers) -->
<mat-icon aria-hidden="true">star</mat-icon>

<!-- Meaningful icon (needs label) -->
<button mat-icon-button aria-label="Add to favorites">
  <mat-icon>favorite</mat-icon>
</button>

<!-- Image with alt text -->
<img src="profile.jpg" alt="User profile picture">

Testing Accessibility

1

Keyboard Testing

Test your application using only the keyboard:
  • Can you reach all interactive elements?
  • Is the focus indicator always visible?
  • Is the tab order logical?
  • Can you activate all buttons and links?
2

Screen Reader Testing

Test with a screen reader:
  • Are all elements properly announced?
  • Do form fields have clear labels?
  • Are error messages read aloud?
  • Can you navigate by headings and landmarks?
3

Automated Testing

Use automated testing tools:
# Install axe-core for testing
npm install --save-dev axe-core
import { runA11yChecks } from '@angular/cdk/testing';

it('should pass accessibility checks', async () => {
  await runA11yChecks(fixture);
});
4

Color Contrast Testing

Use browser DevTools or tools like:
  • Chrome DevTools Lighthouse
  • axe DevTools browser extension
  • WebAIM Color Contrast Checker

CDK Accessibility Tools

The CDK provides utilities for building accessible custom components:

Live Announcer

Announce messages to screen readers:
import { LiveAnnouncer } from '@angular/cdk/a11y';

constructor(private announcer: LiveAnnouncer) {}

announce() {
  this.announcer.announce('Message sent');
}

Focus Trap

Trap focus within a region:
<div cdkTrapFocus>
  <!-- Focus stays here -->
</div>

Focus Monitor

Monitor focus origin:
this.focusMonitor.monitor(element)
  .subscribe(origin => {
    console.log('Focus via:', origin);
  });

List Key Manager

Manage keyboard navigation in lists:
import { FocusKeyManager } from '@angular/cdk/a11y';

this.keyManager = new FocusKeyManager(this.items)
  .withWrap();

Resources

WCAG Guidelines

Web Content Accessibility Guidelines

WAI-ARIA Practices

ARIA Authoring Practices Guide

MDN Accessibility

Learn about web accessibility

axe DevTools

Browser extension for accessibility testing

Next Steps

CDK a11y Module

Explore CDK accessibility utilities

Theming

Learn about color contrast in themes

Components

Explore accessible Material components

Build docs developers (and LLMs) love