Keyboard Navigation Testing: A Developer Complete Guide to WCAG Operability
Keyboard accessibility is one of the most important — and most neglected — aspects of web accessibility. An estimated 2.5 million Americans have motor disabilities that prevent mouse use. If your site can't be operated entirely by keyboard, you're excluding them completely. The Four Core Principles WCAG 2.2 Principle 2 (Operable) contains the keyboard requirements: 2.1.1 Keyboard (AA): All functionality must be operable via keyboard 2.1.2 No Keyboard Trap (AA): If focus moves into a component, it must be possible to move it out 2.4.3 Focus Order (AA): If page can be navigated sequentially, order must be logical and predictable 2.4.7 Focus Visible (AA): Any keyboard-operable UI must have a visible focus indicator 2.4.11 Focus Appearance (AA, new in 2.2): Focus indicator must meet size and contrast requirements Testing Without Automated Tools Start with the basic keyboard test: Unplug (or ignore) your mouse Press Tab to move forward through interactive elements Press Shift+Tab to move backward Use Enter/Space to activate buttons, links, checkboxes Use arrow keys for radio groups, menus, sliders Use Escape to close dialogs and menus Any element you can't reach or activate? That's a WCAG 2.1.1 failure. The Most Common Keyboard Failures Custom dropdowns and menus // ❌ Keyboard inaccessible function Dropdown ({ items }) { return ( < div onClick = { toggle } className = "dropdown" > { items . map ( item => ( < div onClick = { () => select ( item ) } > { item . label } </ div > )) } </ div > ); } // ✅ Fully keyboard accessible function Dropdown ({ items }) { return ( < div role = "combobox" aria-haspopup = "listbox" aria-expanded = { isOpen } tabIndex = { 0 } onKeyDown = { handleKeyDown } // handles Enter, Space, Arrows, Escape className = "dropdown" > < ul role = "listbox" > { items . map (( item , i ) => ( < li key = { item . id } role = "option" tabIndex = { - 1 } aria-selected = { i === activeIndex } onKeyDown = { e => e . key === ' Enter ' && select ( item ) } > { item