Avoiding Shortcut Conflicts with Screen Readers
Permalink to "Avoiding Shortcut Conflicts with Screen Readers"Shortcuts make data apps fast, until they collide with assistive technology. In browse mode, NVDA and JAWS use single letters (H, T, B, F) for quick navigation, so a page-wide “T for table view” shortcut either never fires or hijacks the screen reader’s table key. VoiceOver reserves Control+Option combinations. Insert and Caps Lock are screen reader modifiers. Avoiding conflicts means knowing what is reserved, scoping shortcuts to widgets in focus mode and testing in every mode.
This guide belongs to keyboard shortcuts and command palettes.
Spec reference
Permalink to "Spec reference"- SC 2.1.4 Character Key Shortcuts (A) — single-character shortcuts must be turn-off-able, remappable or active only on focus.
- SC 2.1.1 (A) — shortcuts supplement, never replace, accessible controls.
- aria-keyshortcuts — advertises shortcuts to assistive technology.
- Screen reader key maps — NVDA, JAWS, VoiceOver and Narrator each reserve keys and modes.
When to use — and when not to
Permalink to "When to use — and when not to"Add shortcuts for frequent actions in focused widgets: grid commands, editor actions, command palette opening. Keep the set small and discoverable.
Do not bind page-wide single letters; they fire while users type in search boxes and fight screen reader quick navigation. The misapplication: overriding Ctrl+F for the app’s own search, which breaks the browser’s Find in page that many low-vision users rely on.
Annotated code example
Permalink to "Annotated code example"// Scoped to the grid, modifier-based, ignoring inputs
grid.addEventListener('keydown', e => {
if (e.target.closest('input, textarea, [contenteditable]')) return; // never while typing
if (e.ctrlKey && e.shiftKey && e.key.toLowerCase() === 'e') { // Ctrl+Shift+E: export
e.preventDefault(); exportView();
}
});
<button type="button" aria-keyshortcuts="Control+Shift+E">Export</button> <!-- advertised -->
<div role="grid" aria-label="Invoices" aria-describedby="grid-keys">…</div>
<p id="grid-keys" class="hint">Shortcuts: Ctrl+Shift+E export, Ctrl+Shift+F filter. Press ? for all.</p>
Keyboard & AT behaviour
Permalink to "Keyboard & AT behaviour"| Mode | What reaches your app | Implication |
|---|---|---|
| NVDA/JAWS browse mode | Few keys; letters used for navigation | Page-level shortcuts unreliable |
| Focus mode (in grid, input) | Most keys | Scoped shortcuts work |
| VoiceOver | Most keys except VO combos | Avoid Ctrl+Option |
| Narrator scan mode | Like browse mode | Same as NVDA |
| Pass-through key (NVDA+F2, JAWS Insert+3) | Next key passed through | Document for edge cases |
Step-by-step implementation
Permalink to "Step-by-step implementation"- List candidate shortcuts. Start from the most frequent actions and pick at most eight to ten.
- Check reservations. Compare each against NVDA, JAWS, VoiceOver, Narrator, Windows, macOS and the main browsers. Drop or change any conflict.
- Scope them. Attach handlers to the widget, not the document, so they only apply when focus is there — which also means the screen reader is in focus mode.
- Advertise them. Use
aria-keyshortcutson the matching controls and list them in a help dialog. - Let users change them. Provide a way to remap or disable shortcuts, which also satisfies 2.1.4 for any single-key shortcuts you keep.
Integration context
Permalink to "Integration context"Single-key rules are covered in single-character shortcuts and SC 2.1.4, and advertising in aria-keyshortcuts for grid commands. Remapping is in customizable keyboard shortcuts, and help dialogs in keyboard shortcut help dialogs. Screen reader differences are covered in assistive technology behaviour differences.
Gotchas
Permalink to "Gotchas"Keyboard layouts. e.key varies with layout; Ctrl+Shift+/ on a US layout is a different physical key elsewhere. Prefer letters, and test with other layouts.
macOS modifiers. Map Ctrl to Cmd on macOS where users expect it, and check Cmd combinations against system shortcuts.
role=“application”. It sends all keys to your app in some screen readers, but removes browse mode for that region; use only for truly custom widgets.
Edge cases
Permalink to "Edge cases"- Global palette shortcut. A document-level Ctrl+K to open a command palette is acceptable if it is a modifier combination and works in browse mode; test it.
- Shortcuts in iframes. Embedded grids need their own handlers; the parent page’s shortcuts do not cross frames.
- Conflicts with extensions. Browser extensions may claim combinations; remapping is the user’s escape hatch.
Worked example
Permalink to "Worked example"A trading blotter used page-wide single letters: B for buy, S for sell, F for filter. NVDA users pressed F to find form fields and opened the filter instead; typing a customer name in a search box triggered buys. The team moved shortcuts to Ctrl+Shift combinations scoped to the blotter grid, ignored them in inputs, advertised them with aria-keyshortcuts and added remapping. Accidental orders stopped and screen reader users got their quick navigation back.
Common mistakes
Permalink to "Common mistakes"- Page-wide single-letter shortcuts.
- Overriding browser shortcuts like Ctrl+F.
- Shortcuts that fire while typing.
- Undocumented shortcuts.
Testing checklist
Permalink to "Testing checklist"Testing it with a screen reader
Permalink to "Testing it with a screen reader"With NVDA in browse mode, press each letter your app uses and confirm NVDA’s quick navigation still works. Move focus into the grid (focus mode) and try each shortcut; it should work and NVDA should not intercept it. Repeat with JAWS, whose key map differs, and with VoiceOver, avoiding Control+Option. Type into a search field and press the shortcut letters to confirm nothing fires. Record results per screen reader in your test matrix.
Keeping a shortcut register
Permalink to "Keeping a shortcut register"Keep a single register of every shortcut in the product: the key combination, the scope (which widget), the action, and the result of conflict checks against each screen reader and browser. Review it whenever a team proposes a new shortcut. Without a register, shortcuts accumulate across features and eventually collide with each other as well as with assistive technology, and nobody can say which combinations are safe to use.
Mobile and switch users
Permalink to "Mobile and switch users"Shortcuts are a keyboard convenience, so they never help users on touch screens or switch devices without a keyboard. Every action with a shortcut needs a visible control as well: a toolbar button, a menu item or a command palette entry. On tablets with external keyboards, iPadOS shows available shortcuts when users hold the Command key, but only for native apps; web apps must provide their own help. Switch users scan through visible controls, so a feature reachable only by a shortcut is invisible to them.
Design system notes
Permalink to "Design system notes"Provide a shortcut service with a reserved-key list, scoping, input exclusion and user remapping, and generate the help dialog from it.
FAQ
Permalink to "FAQ"Can I use single-letter shortcuts at all?
Only scoped to a focused widget, or with a way to turn them off or remap.
Why do my shortcuts not work with NVDA?
NVDA is probably in browse mode; scope shortcuts to widgets that put it in focus mode.
Is Ctrl+K safe?
Usually, but check browser conflicts (address bar search in some browsers).
Should I use role application?
Rarely; it disables browse mode in that region.
How do users discover shortcuts?
A help dialog, tooltips and aria-keyshortcuts.
Do function keys work?
Some do, but many are reserved by browsers and operating systems.
Related
Permalink to "Related"- Single-character shortcuts and SC 2.1.4 — the criterion
- Customizable keyboard shortcuts — remapping
- aria-keyshortcuts for grid commands — advertising