VoiceOver
VoiceOver (the built-in screen reader on macOS and iOS) relies on clear semantics, correct names/roles/values, and predictable focus and reading order. To work well in any framework (including Angular), start with semantic HTML and add ARIA only when needed. This aligns with WCAG 2.1/2.2.
Examples
Announcing status updates
- Using an aria-live region (auto announce):
<div aria-live="polite" aria-atomic="true">Loading…</div>
- Using Angular CDK LiveAnnouncer (manual announce):
import { LiveAnnouncer } from '@angular/cdk/a11y';
import { Component } from '@angular/core';
@Component({ selector: 'app-form', template: `...` })
export class FormComponent {
constructor(private liveAnnouncer: LiveAnnouncer) {}
onSubmit() {
this.liveAnnouncer.announce('Form submitted successfully');
}
}
Focus management in a dialog
Using cdkTrapFocus, the focus is trapped inside modal and returned to trigger on close. The cdkTrapFocus attribute is only available in Angular.
<div cdkTrapFocus role="dialog" aria-modal="true" aria-labelledby="dialog-title">
<h2 id="dialog-title">Confirm action</h2>
<button type="button">Confirm</button>
<button type="button">Cancel</button>
</div>
HTML elements
A lot of accessibility is already natively implemented in the different HTML elements.
These elements will give the screen readers context about what the user has focus on.
There are, for example, different kinds of <div> elements that will give screen readers context.
<nav>- Provides a section in the page that is used for navigation links.<footer>- Represents a footer for the page. Typically contains information about the web page and copyright data.<header>- Represents the page header usually used for navigation and logo's.<search>- A block that contains a form or controls related to searching and filtering options.
To find more specific HTML types and ones that can improve the context a screen reader gets see this list of elements.
✅ Correct
<button type="button">Save</button>
❌ Incorrect
<div role="button" tabindex="0">Save</div>
Clear labels
<search>
<input type="search" aria-label="Search site">
</search>
Expose name, role, value on custom controls
<my-toggle role="switch" aria-checked="true"></my-toggle>
👍 Do's
- Use semantic HTML first (
<button>,<nav>,<header>,<main>) - Wrap 3rd‑party components to inject missing
aria-*attributes - Manage focus: move focus into modals on open; return focus on close
- Label everything appropriately (
aria-label,aria-labelledby) - Use ARIA only when needed; avoid redundant roles
- Test via the VoiceOver Rotor: headings, landmarks, and links should be logical
- Ensure keyboard operation with Tab/Shift+Tab/Enter/Space/Arrow keys
👎 Don'ts
- Create fake buttons with
<div role="button">unless truly necessary - Duplicate ARIA roles (e.g.,
<button role="button">) - Hide focusable elements with
aria-hidden="true" - Override tab order with
tabindex> 0 except for well‑justified cases - Omit visible focus styles on custom components
- Rely on visual order that differs from DOM order
Extras
-
WCAG Alignment (Key Principles):
- Perceivable: provide text alternatives (alt,
aria-label,aria-labelledby) - Operable: fully keyboard accessible, no traps, visible focus
- Understandable: clear semantics and predictable structure
- Robust: standard HTML/ARIA compatible with assistive tech
- Perceivable: provide text alternatives (alt,
-
Enabling & testing VoiceOver on macOS:
- Cmd+F5 toggles VoiceOver
- System Settings → Accessibility → VoiceOver for rotor/web settings
- Prefer Safari for VoiceOver testing; cross‑check with NVDA/JAWS on Windows if possible
-
Reading and navigation order:
- DOM order should match the visual and logical order; avoid confusing CSS re‑ordering
-
Headings and landmarks:
- Use
<h1>–<h6>,<main>,<nav>,<footer>to power Rotor navigation
- Use
-
Announcing dynamic changes:
- Prefer polite
aria-liveor targeted announcements via LiveAnnouncer
- Prefer polite
NVDA
NVDA is a voiceover tool used a lot by Windows users. It works differently from, for example, the iOS voiceover. NVDA also supports add-ons that are developed and maintained by the community. But just because the add-on is available doesn't mean they are approved. So when developing for WCAG, it is not necessary to take those add-ons into account. That's why it is also important when testing with NVDA to not have any add-ons installed, because that may impact your experience and may cause bugs that have nothing to do with the webpage you're trying to get WCAG compliant.
NVDA offers a wide list of shortcuts to use to navigate the webpage. For example:
ctrlto make it instantly stop speakingNVDA + tto report the title of the current active windowhto move to the next headingkto move to the next linkdto move to the next landmarkfto move to the next form fieldNVDA + cto read any text in the clipboardNVDA + shift + upArrowto read any selected textporshift + pto skip to the next or previous text paragraph- This will skip clutter such as ads, menus, and headers, making forums and news websites better readable
The NVDA key is a key that can be set by the user. Some of these shortcuts allow you to read certain pieces of content.
Pressing that shortcut three times will also allow the user to make NVDA spell the text. Shortcuts may differ on laptops.
More shortcuts can be found on the NVDA guides page.
Go to the NVDA download page to install it and try it for yourself for free.
Resources
- WCAG 2.2 Overview: https://www.w3.org/TR/WCAG22/
- WCAG 4.1.2 Name, Role, Value: https://www.w3.org/WAI/WCAG22/quickref/#name-role-value
- WAI-ARIA Authoring Practices: https://www.w3.org/WAI/ARIA/apg/
- Apple VoiceOver User Guide (macOS): https://support.apple.com/guide/voiceover/welcome/mac
- MDN: ARIA live regions: https://developer.mozilla.org/docs/Web/Accessibility/ARIA/ARIA_Live_Regions
- Angular CDK LiveAnnouncer: https://material.angular.io/cdk/a11y/api#LiveAnnouncer
- Angular CDK FocusTrap: https://material.angular.io/cdk/a11y/overview#focustrap
- Mdn HTML elements reference: https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements
- NVDA guides: https://download.nvaccess.org/documentation/en/userGuide.html#NVDAQuickStartGuide
- NVDA: https://www.nvaccess.org/download/