Why keyboard accessibility matters

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

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

Essential keyboard interactions

Key Function
Tab Move to next focusable element
Shift + Tab Move to previous focusable element
Enter Activate links, buttons, submit forms
Space Activate buttons, toggle checkboxes
Arrow keys Navigate within components (menus, sliders, tabs)
Escape Close modals, cancel actions
Home / End Jump 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

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

Tab order

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

Maintaining natural tab order

tabindex values

Value Effect Use case
tabindex="0" Makes element focusable in natural order Custom interactive elements
tabindex="-1" Focusable by script only, not Tab key Modal 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

Solutions

Keyboard-accessible elements

Natively keyboard accessible

These HTML elements are keyboard accessible by default:

Require additional work

These need tabindex and keyboard event handlers:

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;
}

Get the full skip link code snippet

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

Keyboard accessibility checklist

Resources