Skip to main content
Operable WCAG 2.1.4

2.1.4 Character Key Shortcuts

If a keyboard shortcut is implemented using only letter, punctuation, number, or symbol characters, then a mechanism is available to turn it off, remap it, or make it active only on focus.

Level A Moderate WCAG 2.1 (new) WCAG 2.2

What this rule means

WCAG 2.1.4 addresses keyboard shortcuts that use single character keys (letters, numbers, punctuation, or symbols) without modifier keys (Ctrl, Alt, Cmd). When such shortcuts exist, the interface must provide at least one of three options: the ability to turn the shortcut off, the ability to remap it to include a modifier key, or limiting the shortcut to be active only when the relevant component has focus.

This criterion was introduced in WCAG 2.1 to address a specific problem: speech input users dictate text, and their software interprets spoken words as individual keystrokes. A single-character shortcut like "s" for search could be accidentally triggered when a user tries to dictate the word "save." Similarly, users with motor impairments may accidentally press character keys while navigating.

Why it matters

Speech input software like Dragon NaturallySpeaking converts spoken words into sequences of key presses. When a web application has single-character shortcuts, normal dictation can trigger unintended commands. For example, saying "send" could activate shortcuts mapped to "s", "e", "n", or "d" in rapid sequence, performing four unintended actions before the user realizes what happened.

Users with motor impairments who use on-screen keyboards or have tremors may also accidentally trigger single-character shortcuts. Without a mechanism to disable or remap these shortcuts, the interface becomes unpredictable and frustrating. Modifier-key combinations (Ctrl+S, Alt+N) do not have this problem because speech input software does not accidentally generate modifier-key combinations.

Related axe-core rules

There are no automated axe-core rules for this criterion. Detecting single-character shortcuts requires manual code review and testing with speech input software, as shortcuts are implemented in JavaScript and cannot be reliably detected through DOM analysis alone.

How to test

Testing requires identifying all keyboard shortcuts and verifying they meet the requirements.

  1. Review the application documentation and code for keyboard shortcut implementations.
  2. Press each letter, number, punctuation, and symbol key individually on the page. Note any shortcuts triggered without a modifier key.
  3. For each single-character shortcut found, verify that a settings mechanism exists to disable or remap it.
  4. Verify that shortcuts scoped to specific components are only active when that component has focus.
  5. If possible, test with speech input software (Dragon NaturallySpeaking) and attempt to dictate text on the page.
  • Check keyboard shortcut documentation (often displayed with "?" key) to inventory all shortcuts.

How to fix

Provide a mechanism to disable, remap, or scope character key shortcuts appropriately.

Shortcut that can be turned off or remapped

// Shortcut configuration object
const shortcuts = {
  search: { key: 's', enabled: true },
  help: { key: '?', enabled: true },
  newItem: { key: 'n', enabled: true },
};

// User preferences loaded from storage
const prefs = loadUserPreferences();
Object.keys(shortcuts).forEach(action => {
  if (prefs[action]) {
    shortcuts[action] = { ...shortcuts[action], ...prefs[action] };
  }
});

document.addEventListener('keydown', (e) => {
  // Skip if user iş typing in an input field
  if (e.target.matches('input, textarea, [contenteditable]')) return;
  // Skip if modifier key iş held (not a single-char shortcut)
  if (e.ctrlKey || e.altKey || e.metaKey) return;

  Object.entries(shortcuts).forEach(([action, config]) => {
    if (config.enabled && e.key === config.key) {
      e.preventDefault();
      executeAction(action);
    }
  });
});

Settings UI for shortcut management

<fieldset>
  <legend>Keyboard Shortcuts</legend>
  <div>
    <label>
      <input type="checkbox" id="shortcuts-enabled"
        checked onchange="toggleAllShortcuts(this.checked)">
      Enable keyboard shortcuts
    </label>
  </div>
  <table>
    <thead>
      <tr><th>Action</th><th>Key</th><th>Enabled</th></tr>
    </thead>
    <tbody>
      <tr>
        <td>Search</td>
        <td><input type="text" value="s" maxlength="1"
          onchange="remapShortcut('search', this.value)"></td>
        <td><input type="checkbox" checked
          onchange="toggleShortcut('search', this.checked)"></td>
      </tr>
    </tbody>
  </table>
</fieldset>

Scope shortcuts to focused components

// Bad: global shortcut with single character
document.addEventListener('keydown', (e) => {
  if (e.key === 'j') scrollToNext();
  if (e.key === 'k') scrollToPrev();
});

// Good: shortcut only active when list is focused
const list = document.getElementById('item-list');
list.addEventListener('keydown', (e) => {
  if (e.key === 'j') scrollToNext();
  if (e.key === 'k') scrollToPrev();
});

Common mistakes

  • Implementing Gmail-style single-key shortcuts (j/k for navigation, s for star, e for archive) without a disable option.
  • Game-like keyboard controls on non-game interfaces without a way to turn them off.
  • Single-character shortcuts that remain active when the user is typing in a search field or text area.
  • No settings page or mechanism for users to view, disable, or remap keyboard shortcuts.
  • Assuming that because shortcuts improve efficiency for some users, they are acceptable without controls.
  • Accesskey attributes using single characters without a modifier — browsers handle these inconsistently.

Resources