The @angular/cdk/a11y package is part of the Angular Component Dev Kit (CDK) and provides a collection of services, directives, SASS mixins, and other utilities to improve the Accessibility (A11y) of your Angular apps.
These tools are invaluable when building reusable, presentation-focused components with screen-reader announcements, robust keyboard and focus support, high-contrast theming, and more. They’re especially useful if you’re creating an Angular Component Library or a Design System.
Below are some of my favorites, along with brief code examples.
LiveAnnouncer for Screen Readers
The first service we want to highlight is the LiveAnnouncer. It allows you to announce messages to screen readers, which is particularly useful for providing feedback after user interactions. It's so simple: I often replace my console.log
calls with announcements.
Here's an example of that:
private readonly liveAnnouncer = inject(LiveAnnouncer);
if (this.flights().length > 0) {
// console.log('Found ' + this.flights().length + ' flights');
this.liveAnnouncer.announce('Found ' + this.flights().length + ' flights');
} else {
// console.log('No flights found');
this.liveAnnouncer.announce('No flights found');
}
Make sure to test your announcements with the use of a screen reader.
Focus Tools
The Angular CDK also includes several tools supporting your focus management.
Focus Trap
The FocusTrap Directive allows you to trap focus within a specific element, ensuring that keyboard navigation remains within that element until the user explicitly exits it.
This is particularly useful for modal dialogs or pop-ups:
<dialog class="awesome-dialog" cdkTrapFocus>
<!–- Yay, focus won't leave this element! -->
</dialog>
If you want focus to jump in automatically, enable the cdkTrapFocusAutoCapture
flag:
<dialog class="awesome-dialog" cdkTrapFocus [cdkTrapFocusAutoCapture]="true">
<!–- Yay, focus won't leave this element! -->
</dialog>
With this flag set to true
, the focus will automatically be captured when the dialog opens. However, it may not always be the best choice to have an element automatically capture focus, so we can avoid this with a trick:
<dialog class="awesome-dialog" cdkTrapFocus [cdkTrapFocusAutoCapture]="true">
<h3 class="awesome-dialog__title" tabindex="-1" cdkFocusInitial>...</h3>
<!–- Yay, focus won't leave this element! -->
</dialog>
By adding cdkFocusInitial
the title will be secretly focused initially. Since it has tabindex -1
, it won't be focusable by keyboard navigation afterward.
Focus Regions
The Regions are a powerful tool that allows you to define a specific area of your application where focus should be managed. This is particularly useful for complex components like dropdowns or menus, where you want to ensure that focus remains within the component while it is open.
cdkFocusRegionStart
cdkFocusRegionEnd
and optionallycdkFocusInitial
Here's an example of how to use the Regions:
<nav>
<a routerLink routerLinkActive="awesome" ariaCurrentWhenActive="page" cdkFocusRegionStart>Focus region start</a></li>
<a routerLink routerLinkActive="awesome" ariaCurrentWhenActive="page">Another focusable link</a></li>
<a routerLink routerLinkActive="awesome" ariaCurrentWhenActive="page" cdkFocusInitial>Initially focused</a></li>
<a routerLink routerLinkActive="awesome" ariaCurrentWhenActive="page" cdkFocusRegionEnd>Focus region end</a></li>
</nav>
Note: To learn about the ariaCurrentWhenActive
please read my post on Accessible Angular Routes
Focus Monitor
The FocusMonitor is a service that allows you to monitor focus changes within your application. It can be used to track when an element gains or loses focus, which is particularly useful for debugging focus-related issues.
This service can be injected into your components or services, and you can subscribe to focus changes:
import { Component, DestroyRef, effect, ElementRef, inject, viewChild } from '@angular/core';
import { FocusMonitor, FocusOrigin } from '@angular/cdk/a11y';
@Component({
selector: 'app-navbar',
template: `<nav #observed class="awesome-nav-cnt"><!-- children --></nav>`,
})
export class AwesomeFocusMonitorComponent {
private readonly destroyRef = inject(DestroyRef);
private readonly focusMonitor = inject(FocusMonitor);
private readonly observedElementRef = viewChild.required<ElementRef<HTMLElement>>('observed');
constructor() {
effect(() => {
const observedElementRef = this.observedElementRef(); // effect will run when the view is initialized
this.focusMonitor.monitor(observedElementRef, true).subscribe((origin: FocusOrigin) => console.log(origin));
this.destroyRef.onDestroy(() => this.focusMonitor.stopMonitoring(observedElementRef));
});
}
}
This is particularly useful for debugging focus-related issues, as it allows you to see when an element gains or loses focus.
FocusOrigin
can be one of the following:
'mouse'
the element was focused with the mouse'keyboard'
it was focused with the keyboard'touch'
it was focused by touching on a touchscreen'program'
it was focused programmatically, whereasnull
indicates the element was blurred
So, this is also useful to check if a touch device is being used 😏
Styling utilities
The Angular A11y package also includes two useful Sass mixins.
Hidden Elements
Screen readers and other assistive technology skip elements that have display: none
, visibility: hidden
, opacity: 0
, height: 0
, or width: 0
. In some cases, you may need to visually hide an element while keeping it available to assistive technology (e.g. Screen Readers).
@use '@angular/cdk';
@include cdk.a11y-visually-hidden();
<div class="awesome-toggle">
<input type="checkbox" class="cdk-visually-hidden" />
</div>
High Contrast Mode
Some operating systems and/or devices include a High Contrast Mode. The Angular A11y package provides a Sass mixin that lets you define styles that only apply in high contrast mode. To create a high contrast style, just wrap it into the high-contrast mixin.
@use '@angular/cdk';
button {
@include cdk.high-contrast {
outline: 3px solid gold;
}
}
The mixin works by targeting the forced-colors media query.
Accessibility Workshop
For those looking to deepen their Angular expertise, we offer a range of workshops – both in English and German:
- ♿ Accessibility Workshop
- 📈 Best Practices Workshop (including accessibility-related topics)
- 🚀 Performance Workshop
Conclusion
With these tools, you can significantly enhance the accessibility of your Angular Apps. They help ensure that your components are not only functional but also user-friendly for everyone, including those with disabilities.
One last thing: In this Code lab by Google, you can find some exercises on the most important Angular CDK A11y tools https://codelabs.developers.google.com/angular-a11y#8
That's all folks!
This is the last edition of our A11y series. I hope you found it helpful and learned something new about making your Angular Apps more accessible and user-friendly for all of us, and that you are ready for the European Accessibility Act (EAA). If uncertain, please go back to the start of the A11y blog series.
This blog post was written by Alexander Thalhammer. Follow me on Linkedin, X or giThub.
References
- Angular CDK Accessibility – official docs
- Google codelab on A11y by Emma Twersky