Keyboard Navigation Testing Guide: How to Test Website Accessibility
Why Keyboard Accessibility Matters
Not everyone uses a mouse. Many people navigate websites using only their keyboard:
If your site isn't keyboard accessible, these users simply can't use it. It's also a core WCAG requirement and common source of ADA lawsuits.
The Basics: How Keyboard Navigation Works
Users navigate with these keys:
| Key | Action |
|---|---|
| Tab | Move to next interactive element |
| Shift + Tab | Move to previous interactive element |
| Enter | Activate links and buttons |
| Space | Activate buttons, toggle checkboxes |
| Arrow keys | Navigate within components (menus, tabs, radio groups) |
| Escape | Close modals, menus, dropdowns |
How to Test Keyboard Navigation
Step 1: Put Away Your Mouse
Seriously. Unplug it or move it out of reach. You'll instinctively reach for it otherwise.
Step 2: Start at the Top
1. Click in the browser's address bar
2. Press Tab to enter the page
3. Keep pressing Tab to move through all interactive elements
Step 3: Check These Things
As you tab through, ask yourself:
Can I see where I am?
Is the order logical?
Can I access everything?
Can I get out?
Common Issues and How to Fix Them
Issue 1: No Visible Focus Indicator
The focus indicator shows which element is currently selected. Never remove it:
/* Never do this */
*:focus {
outline: none;
}
/* Do this instead - customize but keep visible */
*:focus {
outline: 2px solid #0066cc;
outline-offset: 2px;
}
/* Or use focus-visible for mouse users */
*:focus:not(:focus-visible) {
outline: none;
}
*:focus-visible {
outline: 2px solid #0066cc;
outline-offset: 2px;
}Issue 2: Interactive Elements Not Focusable
Only certain elements are naturally focusable:
<a href>)<button>)<input>, <select>, <textarea>)If you make other elements interactive, add tabindex="0":
<!-- Bad: div with click handler isn't focusable -->
<div onclick="doSomething()">Click me</div>
<!-- Good: Use a button -->
<button onclick="doSomething()">Click me</button>
<!-- If you must use a div, add tabindex and role -->
<div
role="button"
tabindex="0"
onclick="doSomething()"
onkeydown="if(event.key === 'Enter') doSomething()"
>
Click me
</div>Issue 3: Wrong Tab Order
Tab order follows the DOM order, not visual order. If your CSS reorders elements visually, the tab order will be confusing.
/* This causes tab order issues */
.sidebar {
order: 2;
}
.main-content {
order: 1;
}Fix: Match your HTML structure to your visual layout, or use tabindex carefully (though this is hard to maintain).
Issue 4: Keyboard Traps
A keyboard trap occurs when a user can tab into an element but can't tab out. Common culprits:
// Proper modal focus trapping
const modal = document.querySelector('.modal');
const focusableElements = modal.querySelectorAll(
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
);
const firstElement = focusableElements[0];
const lastElement = focusableElements[focusableElements.length - 1];
modal.addEventListener('keydown', (e) => {
if (e.key === 'Tab') {
if (e.shiftKey && document.activeElement === firstElement) {
e.preventDefault();
lastElement.focus();
} else if (!e.shiftKey && document.activeElement === lastElement) {
e.preventDefault();
firstElement.focus();
}
}
if (e.key === 'Escape') {
closeModal();
}
});Issue 5: Dropdown Menus Not Keyboard Accessible
Menus should work with arrow keys, not just Tab:
menu.addEventListener('keydown', (e) => {
const items = menu.querySelectorAll('[role="menuitem"]');
const currentIndex = Array.from(items).indexOf(document.activeElement);
switch (e.key) {
case 'ArrowDown':
e.preventDefault();
items[(currentIndex + 1) % items.length].focus();
break;
case 'ArrowUp':
e.preventDefault();
items[(currentIndex - 1 + items.length) % items.length].focus();
break;
case 'Escape':
closeMenu();
menuButton.focus();
break;
}
});Issue 6: Skip Link Missing
Users shouldn't have to tab through your entire navigation on every page. Add a skip link:
<!-- First element in body -->
<a href="#main-content" class="skip-link">
Skip to main content
</a>
<!-- Style it to appear on focus -->
<style>
.skip-link {
position: absolute;
top: -40px;
left: 0;
padding: 8px;
background: #000;
color: #fff;
z-index: 100;
}
.skip-link:focus {
top: 0;
}
</style>
<!-- Main content target -->
<main id="main-content">
...
</main>Testing Tools
Browser DevTools
Chrome DevTools can show tab order:
1. Open DevTools (F12)
2. Go to Elements panel
3. Press Ctrl+Shift+P (Cmd+Shift+P on Mac)
4. Type "Show Accessibility" and select it
5. Check the accessibility tree
Automated Testing
While automated tools can't fully test keyboard navigation, they can catch:
Scan your site with ClearA11y to identify these issues automatically.
Keyboard Testing Checklist
Make It a Habit
Every time you add a new interactive feature, test it with your keyboard. It takes 30 seconds and catches issues before they ship.
For a complete accessibility audit, scan your website with ClearA11y and get a detailed report of all keyboard and other accessibility issues.
Check Your Site's Accessibility
Find and fix accessibility issues with AI-powered code suggestions.
Start Free ScanStay Updated on Web Accessibility
Get practical accessibility tips, WCAG updates, and guides delivered to your inbox. No spam, unsubscribe anytime.
We respect your privacy. Unsubscribe at any time.