Skip to main content

Welcome to our new website! The content and organization have been heavily redone and we want to hear from you! 
Submit feedback

Keyboard Accessibility

Ensuring all functionality is available without a mouse.

⌨️ WCAG 2.1.1 & 2.1.2

Why keyboard accessibility matters

Many users cannot use a mouse and rely on keyboard (or keyboard-emulating devices):

  • Motor disabilities: Users with limited fine motor control
  • Blind users: Screen reader users navigate with keyboard
  • Repetitive strain injuries: Keyboard is often easier than mouse
  • Switch device users: Devices emulate keyboard input
  • Power users: Many prefer keyboard for efficiency

WCAG requirement: All functionality must be operable through a keyboard interface (2.1.1 Keyboard).

Essential keyboard interactions

KeyFunction
TabMove to next focusable element
Shift + TabMove to previous focusable element
EnterActivate links, buttons, submit forms
SpaceActivate buttons, toggle checkboxes
Arrow keysNavigate within components (menus, sliders, tabs)
EscapeClose modals, cancel actions
Home / EndJump to first/last item in a list

Focus indicators

WCAG 2.4.7 requires that keyboard focus is visible. Users must be able to see which element they're on.

Good focus indicators

  • High contrast outline (not just color change)
  • Visible on all backgrounds
  • At least 2px thick
  • Consistent across the site

CSS focus styles

/* Good focus style */
:focus {
  outline: 3px solid #0C234B;
  outline-offset: 2px;
}

/* Or use focus-visible for keyboard-only focus */
:focus-visible {
  outline: 3px solid #0C234B;
  outline-offset: 2px;
}

/* NEVER do this: */
:focus {
  outline: none; /* ❌ Removes focus indicator! */
}

Focus management requirements

  • Never remove focus outlines without providing alternative
  • Ensure focus is visible on all backgrounds (light and dark)
  • Focus should not be obscured by sticky headers or modals (WCAG 2.4.11)

Tab order

Tab order should follow a logical reading order (typically left-to-right, top-to-bottom in English).

Maintaining natural tab order

  • Use semantic HTML elements in logical order
  • Avoid using tabindex values greater than 0
  • Test by tabbing through the page

tabindex values

ValueEffectUse case
tabindex="0"Makes element focusable in natural orderCustom interactive elements
tabindex="-1"Focusable by script only, not Tab keyModal dialogs, error messages
tabindex="1+"Overrides natural order⚠️ Avoid — causes confusion

Avoiding keyboard traps

WCAG 2.1.2: Users must be able to navigate away from any component using standard keyboard.

Common trap scenarios

  • Modal dialogs that don't allow Tab to exit
  • Embedded content (iframes, video players) that capture keyboard
  • Rich text editors
  • Interactive maps

Solutions

  • Modal dialogs: Allow Escape to close
  • Embedded content: Ensure Tab moves past the embed
  • Provide clear instructions for exiting complex widgets
  • Test thoroughly by tabbing through

Keyboard-accessible elements

Natively keyboard accessible

These HTML elements are keyboard accessible by default:

  • <a href="..."> — Links
  • <button> — Buttons
  • <input> — Form inputs
  • <select> — Dropdown menus
  • <textarea> — Text areas

Require additional work

These need tabindex and keyboard event handlers:

  • <div onclick="..."> — Use <button> instead!
  • Custom dropdowns and menus
  • Drag-and-drop interfaces
  • Custom sliders and controls

Making custom elements keyboard accessible

<!-- ❌ Bad: div used as button -->
<div onclick="doAction()">Click me</div>

<!-- ✓ Good: use actual button -->
<button onclick="doAction()">Click me</button>

<!-- If you must use div, add keyboard support -->
<div role="button" tabindex="0" 
     onclick="doAction()" 
     onkeydown="if(event.key==='Enter'||event.key===' ')doAction()">
  Click me
</div>

Skip links allow keyboard users to bypass repetitive content (navigation) and jump to main content.

Implementation

<!-- Add as first element in body -->
<a href="#maincontent" class="skip-link">Skip to main content</a>

<!-- Add id to main content -->
<main id="maincontent">
  ...
</main>

<!-- CSS for skip link -->
.skip-link {
  position: absolute;
  top: -40px;
  left: 0;
  background: #0C234B;
  color: white;
  padding: 8px;
  z-index: 100;
}

.skip-link:focus {
  top: 0;
}

Testing keyboard accessibility

Manual testing process

  1. Put mouse aside — Only use keyboard
  2. Tab through entire page — Can you reach everything?
  3. Check focus visibility — Can you always see where you are?
  4. Check logical order — Does tab order make sense?
  5. Test all interactions — Can you activate buttons, submit forms?
  6. Test complex widgets — Menus, modals, sliders, carousels
  7. Check for traps — Can you always Tab away?

Tools

  • Accessibility Insights: Tab Stops feature visualizes tab order
  • Browser DevTools: Focus indicator testing
  • WAVE: Shows errors related to keyboard access

Keyboard accessibility checklist

  • check_box_outline_blank All interactive elements reachable by Tab
  • check_box_outline_blank Focus indicator always visible
  • check_box_outline_blank Tab order matches visual/reading order
  • check_box_outline_blank No keyboard traps
  • check_box_outline_blank Enter/Space activates buttons and links
  • check_box_outline_blank Escape closes modals and menus
  • check_box_outline_blank Skip link provided
  • check_box_outline_blank Custom widgets follow ARIA patterns
  • check_box_outline_blank Focus not obscured by sticky elements

Resources