Accessibility for Angular apps.
Angular has the strongest built-in accessibility toolkit of any major framework (the Angular CDK a11y module is best-in-class), and the highest opportunity to ignore it. The patterns and audit workflow for teams that want to use it.
What goes wrong in Angular projects.
Router navigation without focus management
Single-page apps navigate without page reload; screen readers do not announce the new route. Use Angular's `RouteReuseStrategy` + manual `Title` updates + focus the new route's heading. Or use Angular CDK `LiveAnnouncer`.
Reactive forms without programmatic labels
`formControlName` does not auto-create labels. Always pair with `<label for>` or `[attr.aria-label]`. Angular form errors via `*ngIf` also need aria-live for screen reader announcement.
Material Dialog without focus restore
Angular Material's `MatDialog` mostly handles focus correctly but custom dialogs built on `Overlay` from the CDK often miss the close-focus-return. Verify in your test plan.
Custom directives stripping accessibility attributes
Directives that manipulate the DOM imperatively can drop ARIA attributes set in the template. Use `Renderer2` carefully and add accessibility tests.
Lazy-loaded modules breaking page title
When routes lazy-load, page title updates can lag or miss. Subscribe to `NavigationEnd` and update `Title` service explicitly per route. WCAG 2.4.2 requires accurate page titles.
CDK Overlay positioning hiding focus
Tooltips and overlays positioned at the viewport edge can clip focused content. Test with keyboard at small viewport sizes.
The Angular accessibility stack we recommend.
@angular/cdk/a11y
npm i @angular/cdkBest-in-class accessibility module: FocusTrap, LiveAnnouncer, FocusMonitor, AriaDescriber, ListKeyManager. Use these instead of hand-rolled equivalents.
codelyzer (deprecated, replaced by eslint)
For older Angular projects on TSLint. Has a11y rules. New projects: use eslint-plugin-jsx-a11y patterns adapted to Angular templates.
@angular-eslint/eslint-plugin-template
npm i @angular-eslint/eslint-plugin-templateModern eslint integration for Angular templates. Includes accessibility rules: `@angular-eslint/template/click-events-have-key-events`, `accessibility-alt-text`, `accessibility-label-has-associated-control`.
axe-core CLI
npm i axe-coreRun as part of e2e tests. Combined with Cypress/Playwright via `@axe-core/playwright` or `cypress-axe` for automated assertions.
Angular Material
npm i @angular/materialBuilt on the CDK, components have correct accessibility baseline. Stick to standard components unless you have a strong reason to roll custom.
Step-by-step for a Angular accessibility audit.
- 1
Enable angular-eslint template a11y rules
Add `@angular-eslint/template/accessibility-*` rules to your eslint config. Run on existing code; review first violations.
- 2
Use the CDK a11y module
For any custom widget that needs keyboard navigation or focus management, use `cdkTrapFocus`, `LiveAnnouncer`, `FocusKeyManager` from `@angular/cdk/a11y` rather than reinventing.
- 3
Manage page titles per route
Use Angular `Title` service in route resolvers or `data: { title }` + a `TitleStrategy`. Critical for WCAG 2.4.2 in SPAs.
- 4
Add axe-core to e2e suite
Cypress: `cypress-axe`. Playwright: `@axe-core/playwright`. Block deploys on critical/serious violations.
- 5
AccessProof external scan in CI
Scan the deployed Angular app from outside. Catches issues axe-in-test cannot (post-hydration, dynamic content, real-network behavior).
Run a WCAG audit on your Angular site in 42 seconds.
External scan — no JS injected into your app
WCAG 2.2 + Section 508 + EN 301 549 in one pass
Court-ready PDF with element selectors
CI/CD gate — block deploys on regression
Works with Angular on any hosting (Vercel, Netlify, Fly, self-hosted)
Free plan — 1 site, monthly scan
Angular-specific questions.
Why is @angular/cdk/a11y considered better than React equivalents?
It was designed alongside Angular Material with the Angular team in close coordination. The pattern is consistent (services + directives), the documentation is precise, and the surface (FocusTrap, LiveAnnouncer, ListKeyManager, AriaDescriber) covers the recurring accessibility needs without overlap. React equivalents (react-aria, radix, headlessui) are excellent too but more fragmented across libraries.
Should I use Angular Material or build custom components?
Angular Material covers ~80% of common UI patterns with correct accessibility baselines. For new projects, use Material unless you have specific design requirements that conflict. For custom components, use the CDK primitives (Overlay, Portal, FocusTrap, LiveAnnouncer) — they handle the hard a11y parts.
How do I test SPA route announcements?
Manual screen reader test (NVDA/VoiceOver) is the gold standard. For automated tests, you can spy on `LiveAnnouncer.announce()` calls if you use the CDK service. For e2e, axe-core does not test announcement quality — it only checks the DOM is structured correctly.
Is server-side rendering with Angular Universal accessibility-friendly?
SSR helps WCAG 2.4.2 (page titled at first paint) and avoids client-only rendering accessibility delays. But hydration mismatches in Universal can cause flickers in aria-live regions or focus management; test the hydration path explicitly with screen readers.