Keyboard Navigation and Focus Management: A Developer's Guide
Keyboard accessibility is the cornerstone of web accessibility. Every user who cannot use a mouse — whether due to motor impairment, visual impairment, temporary injury, or preference — depends on keyboard navigation to interact with your website. Screen readers, switch devices, and voice control systems all ultimately translate user input into keyboard-equivalent commands. If your site does not work with a keyboard, it does not work for a substantial portion of your audience.
The Core Requirements
SC 2.1.1 Keyboard (Level A) requires that all functionality is available through a keyboard interface. Every link, button, form control, menu, dialog, slider, and interactive element must be reachable and operable using the keyboard alone.
SC 2.1.2 No Keyboard Trap (Level A) requires that users can always move focus away from any element. If focus enters a component, there must be a documented way to move focus out — typically using Tab, Shift+Tab, Escape, or arrow keys.
SC 2.4.3 Focus Order (Level A) requires that when content can be navigated sequentially, the focus order preserves meaning and operability. Focus should generally follow the visual layout — left to right, top to bottom in left-to-right languages.
SC 2.4.7 Focus Visible (Level A) requires that the keyboard focus indicator is visible. Users must be able to see which element currently has focus.
WCAG 2.2 Focus Criteria
WCAG 2.2 added important new criteria related to focus:
SC 2.4.11 Focus Not Obscured – Minimum (Level AA) addresses a common frustration: focused elements hidden behind sticky headers, cookie banners, chat widgets, or other fixed-position content. The focused element must not be entirely hidden by author-created content.
SC 2.4.12 Focus Not Obscured – Enhanced (Level AAA) strengthens this to require that no part of the focused element or its focus indicator is hidden.
SC 2.4.13 Focus Appearance (Level AAA) defines specific visual requirements for focus indicators: at minimum, a 2-pixel wide perimeter of the unfocused component with at least 3:1 contrast ratio between the focused and unfocused states.
Understanding tabindex
The tabindex attribute controls keyboard focusability:
tabindex="0" places the element in the natural tab order based on its DOM position. Use this to make non-interactive elements focusable when you have given them an interactive role via ARIA.
tabindex="-1" removes the element from the tab order but allows it to receive focus programmatically via JavaScript's focus() method. Use this for elements that should receive focus in specific circumstances (such as when a dialog opens) but should not be in the normal tab sequence.
Positive tabindex values (1, 2, 3...) should almost never be used. They override the natural DOM order and create confusing, unpredictable focus sequences. If you need to change focus order, change the DOM order instead.
Focus Management in Single-Page Applications
Single-page applications present unique focus challenges because page navigation happens within the same document. When a user activates a route change, new content loads without a full page refresh, and the browser does not automatically manage focus the way it does with traditional page loads.
When a route change occurs, move focus to the new content — typically to the main heading of the new view or to the main content container. Announce the page change to screen readers, either through a live region or by updating the document title and moving focus to an element that includes the new page context.
Modal Dialog Focus Management
Modal dialogs require careful focus management:
When the dialog opens, move focus to the first focusable element within the dialog (or to the dialog itself if it has an accessible label).
Trap focus within the dialog while it is open — Tab and Shift+Tab should cycle through only the elements inside the dialog, never escaping to the content behind it.
When the dialog closes, return focus to the element that triggered the dialog. This ensures the user resumes navigation from where they left off.
Allow Escape to close the dialog.
Skip Links
A skip link is a mechanism that allows keyboard users to bypass repeated blocks of content, such as the site navigation, and jump directly to the main content. It is typically implemented as the very first focusable element on the page, often hidden until it receives focus.
A basic implementation creates an anchor link pointing to the main content region. The link is positioned off-screen by default and becomes visible when it receives keyboard focus, allowing users to activate it to jump past the navigation.
Roving tabindex Pattern
For composite widgets like toolbars, tab lists, and radio groups, the roving tabindex pattern provides efficient keyboard navigation. Instead of making every item in the group tabbable (which creates excessive tab stops), only the currently active item has tabindex="0" while all other items have tabindex="-1". Arrow keys move focus between items, updating the tabindex values as focus moves.
This pattern means the user can Tab into the widget, use arrow keys to navigate within it, and Tab out to continue to the next element — matching the expected behavior for native widget patterns.
Czy Twoja strona jest dostępna?
Przeskanuj swoją stronę za darmo i poznaj swój wynik WCAG w kilka minut.
Przeskanuj stronę za darmo