Overview for a11y
The a11y
package provides a number of tools to improve accessibility, described below.
ListKeyManager
ListKeyManager
manages the active option in a list of items based on keyboard interaction.
Intended to be used with components that correspond to a role="menu"
or role="listbox"
pattern.
Basic usage
Any component that uses a ListKeyManager
will generally do three things:
- Create a
@ViewChildren
query for the options being managed. - Initialize the
ListKeyManager
, passing in the options. - Forward keyboard events from the managed component to the
ListKeyManager
.
Each option should implement the ListKeyManagerOption
interface:
interface ListKeyManagerOption {
disabled?: boolean;
getLabel?(): string;
}
Wrapping
Navigation through options can be made to wrap via the withWrap
method
this.keyManager = new FocusKeyManager(...).withWrap();
Types of list key managers
There are two varieties of ListKeyManager
, FocusKeyManager
and ActiveDescendantKeyManager
.
FocusKeyManager
Used when options will directly receive browser focus. Each item managed must implement the
FocusableOption
interface:
interface FocusableOption extends ListKeyManagerOption {
focus(): void;
}
ActiveDescendantKeyManager
Used when options will be marked as active via aria-activedescendant
.
Each item managed must implement the
Highlightable
interface:
interface Highlightable extends ListKeyManagerOption {
setActiveStyles(): void;
setInactiveStyles(): void;
}
Each item must also have an ID bound to the listbox's or menu's aria-activedescendant
.
TreeKeyManager
TreeKeyManager
manages the active option in a tree view. Use this key manager for
components that implement a role="tree"
pattern.
Basic usage
Any component that uses a TreeKeyManager
should do three things:
- Create a
@ViewChildren
query for the tree items being managed. - Initialize the
TreeKeyManager
, passing in the options. - Forward keyboard events from the managed component to the
TreeKeyManager
viaonKeydown
.
Each tree item should implement the TreeKeyManagerItem
interface.
Focus management
The TreeKeyManager
will handle focusing the appropriate item on keyboard interactions.
tabindex
should also be set by the component when the active item changes. This can be listened to
via the change
property on the TreeKeyManager
. In particular, the tree should only have a
tabindex
set if there is no active item, and should not have a tabindex
set if there is an
active item. Only the HTML node corresponding to the active item should have a tabindex
set to
0
, with all other items set to -1
.
FocusTrap
The cdkTrapFocus
directive traps Tab key focus within an element. This is intended to
be used to create accessible experience for components like
modal dialogs, where focus must be
constrained.
This directive is declared in A11yModule
.
Example
<div class="my-inner-dialog-content" cdkTrapFocus>
<!-- Tab and Shift + Tab will not leave this element. -->
</div>
This directive will not prevent focus from moving out of the trapped region due to mouse interaction.
Regions
Regions can be declared explicitly with an initial focus element by using
the cdkFocusRegionStart
, cdkFocusRegionEnd
and cdkFocusInitial
DOM attributes.
cdkFocusInitial
specifies the element that will receive focus upon initialization of the region.
cdkFocusRegionStart
and cdkFocusRegionEnd
define the region within which focus will be
trapped. When using the tab key, focus will move through this region and wrap around on either end.
For example:
<a mat-list-item routerLink cdkFocusRegionStart>Focus region start</a>
<a mat-list-item routerLink>Link</a>
<a mat-list-item routerLink cdkFocusInitial>Initially focused</a>
<a mat-list-item routerLink cdkFocusRegionEnd>Focus region end</a>
Note: If you're using cdkFocusInitial
together with the CdkTrapFocus
directive, nothing
will happen unless you've enabled the cdkTrapFocusAutoCapture
option as well. This is due to
CdkTrapFocus
not capturing focus on initialization by default.
InteractivityChecker
InteractivityChecker
is used to check the interactivity of an element, capturing disabled,
visible, tabbable, and focusable states for accessibility purposes. See the API docs for more
details.
LiveAnnouncer
LiveAnnouncer
is used to announce messages for screen-reader users using an aria-live
region.
See the W3C's WAI-ARIA
for more information on aria-live regions.
Example
@Component({...})
export class MyComponent {
constructor(liveAnnouncer: LiveAnnouncer) {
liveAnnouncer.announce("Hey Google");
}
}
FocusMonitor
The FocusMonitor
is an injectable service that can be used to listen for changes in the focus
state of an element. It's more powerful than just listening for focus
or blur
events because it
tells you how the element was focused (via the mouse, keyboard, touch, or programmatically). It also
allows listening for focus on descendant elements if desired.
To listen for focus changes on an element, use the monitor
method which takes an element to
monitor and an optional boolean flag checkChildren
. Passing true for checkChildren
will tell the
FocusMonitor
to consider the element focused if any of its descendants are focused. This option
defaults to false
if not specified. The monitor
method will return an Observable that emits the
FocusOrigin
whenever the focus state changes. The FocusOrigin
will be one of the following:
'mouse'
indicates the element was focused with the mouse'keyboard'
indicates the element was focused with the keyboard'touch'
indicates the element was focused by touching on a touchscreen'program'
indicates the element was focused programmaticallynull
indicates the element was blurred
In addition to emitting on the observable, the FocusMonitor
will automatically apply CSS classes
to the element when focused. It will add .cdk-focused
if the element is focused and will further
add .cdk-${origin}-focused
(with ${origin}
being mouse
, keyboard
, touch
, or program
) to
indicate how the element was focused.
Note: currently the FocusMonitor
emits on the observable outside of the Angular zone. Therefore,
if you markForCheck
in the subscription you must put yourself back in the Angular zone.
focusMonitor.monitor(el).subscribe(origin => this.ngZone.run(() => /* ... */ ));
Any element that is monitored by calling monitor
should eventually be unmonitored by calling
stopMonitoring
with the same element.
Focus Monitored Subtree (blurred)
It is possible to falsify the FocusOrigin
when setting the focus programmatically by using the
focusVia
method of FocusMonitor
. This method accepts an element to focus and the FocusOrigin
to use. If the element being focused is currently being monitored by the FocusMonitor
it will
report the FocusOrigin
that was passed in. If the element is not currently being monitored, it
will just be focused like normal.
cdkMonitorElementFocus and cdkMonitorSubtreeFocus
For convenience, the CDK also provides two directives that allow for easily monitoring an element.
cdkMonitorElementFocus
is the equivalent of calling monitor
on the host element with
checkChildren
set to false
. cdkMonitorSubtreeFocus
is the equivalent of calling monitor
on
the host element with checkChildren
set to true
. Each of these directives has an @Output()
cdkFocusChange
that will emit the new FocusOrigin
whenever it changes.
Focus Monitored Subtree (blurred)
Styling utilities
The cdk/a11y
package comes with Sass mixins that produce styles useful for building
accessible experiences.
Hiding elements in an accessible way
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. You can do so using
the a11y-visually-hidden
Sass mixin, which emits the .cdk-visually-hidden
CSS class.
If you're using Angular Material, this class is included automatically by Angular Material's theming system. Otherwise, you can include this mixin in a global stylesheet.
@use '@angular/cdk';
@include cdk.a11y-visually-hidden();
<div class="custom-checkbox">
<input type="checkbox" class="cdk-visually-hidden">
</div>
Targeting high contrast users
Some operating systems include an accessibility feature called High Contrast Mode. The
cdk/a11y
package provides a Sass mixin that lets you define styles that only apply in high
contrast mode. To create a high contrast style, define your style inside the high-contrast
mixin.
The mixin works by targeting the forced-colors
media query.
@use '@angular/cdk';
button {
@include cdk.high-contrast {
outline: solid 1px;
}
}
The high-contrast
mixin accepts the optional $target
parameter which allows you to specify
the value of the forced-color
media query. Its value can be either active
or none
.