Accessibility Fix Guide

How to Fix Keyboard Navigation Issues for WCAG and ADA Accessibility

Keyboard navigation is one of the clearest tests of whether a website is actually usable, not just visually polished. If a visitor cannot move through your navigation, open a menu, submit a form, close a popup, or complete a checkout flow without a mouse, the site has an accessibility problem.

Many people rely on keyboard access. Some users cannot use a mouse because of mobility disabilities. Some use assistive technology that depends on keyboard interaction. Some use switch devices, voice control, or other input systems that interact with the page in keyboard-like ways. Even people without permanent disabilities may use keyboard navigation because of a temporary injury, broken trackpad, power-user habits, or preference.

A site can look perfectly normal and still fail keyboard testing. The most common problems include missing focus styles, interactive elements that cannot be reached with the Tab key, dropdowns that only open on hover, modals that trap users incorrectly, custom buttons built with div elements, and focus order that jumps around the page in a confusing way.

This page is informational and is not legal advice. Accessibility obligations vary by site and organization, and automated checks should be paired with manual testing.

What keyboard navigation means

Keyboard navigation means a user can operate the page using standard keyboard commands. The most common keys are:

A keyboard-accessible page does not require a mouse for core tasks. A user should be able to navigate, understand where they are, interact with controls, and recover from mistakes using the keyboard alone.

WCAG criteria related to keyboard navigation

WCAG 2.1.1 — Keyboard

All functionality should be operable through a keyboard interface, except where the underlying function requires path-based input, such as freehand drawing. In practical terms, links, buttons, menus, form fields, tabs, accordions, modal dialogs, checkout actions, and search controls should be usable without a mouse.

WCAG 2.1.2 — No Keyboard Trap

A user should not get stuck in one part of the page. If focus can move into a component, the user must be able to move out of it using the keyboard. This commonly affects modals, embedded widgets, chat windows, date pickers, and third-party forms.

WCAG 2.4.3 — Focus Order

When a user tabs through the page, the order should preserve meaning and operability. Focus should move in a logical order that matches the visual layout and task flow.

WCAG 2.4.7 — Focus Visible

Users need to see where keyboard focus is. Missing focus indicators are so common that they deserve their own fix guide, but they are also part of keyboard usability.

Common keyboard navigation failures

Failure 1: Clickable divs and spans

A common accessibility issue happens when developers build a clickable control with a non-interactive element.

Problem:

<div class="button" onclick="submitForm()">
  Submit
</div>

This may respond to a mouse click, but it is not a real button. It may not receive keyboard focus. It may not activate with Enter or Space. It may not be announced correctly by assistive technology.

Better:

<button type="button" class="button" onclick="submitForm()">
  Submit
</button>

Native buttons already support keyboard focus, activation, disabled state, and assistive technology semantics. In most cases, the simplest fix is to use the correct HTML element.

If the control navigates somewhere, use a link:

<a href="/pricing" class="button-link">
  View pricing
</a>

If the control performs an action on the current page, use a button:

<button type="button">
  Open menu
</button>

Failure 2: Hover-only menus

Navigation menus often work with a mouse but fail for keyboard users.

Problem:

.nav-item:hover .submenu {
  display: block;
}

This opens the submenu only when the user hovers with a mouse. A keyboard user may tab to the menu item but never see the submenu.

Better:

<button
  type="button"
  class="menu-button"
  aria-expanded="false"
  aria-controls="services-menu"
>
  Services
</button>

<ul id="services-menu" hidden>
  <li><a href="/services/audit">Accessibility audit</a></li>
  <li><a href="/services/remediation">Remediation</a></li>
</ul>

Then use JavaScript to toggle hidden and update aria-expanded.

const button = document.querySelector(".menu-button");
const menu = document.getElementById("services-menu");

button.addEventListener("click", () => {
  const expanded = button.getAttribute("aria-expanded") === "true";
  button.setAttribute("aria-expanded", String(!expanded));
  menu.hidden = expanded;
});

This creates a menu that can be opened by keyboard and mouse.

Failure 3: Focus order does not match the page

Focus order should generally follow the visual order of the page. Problems appear when CSS reorders content, when elements are absolutely positioned, or when tabindex is used incorrectly.

Avoid positive tabindex values:

<a href="/contact" tabindex="3">Contact</a>
<a href="/pricing" tabindex="1">Pricing</a>
<a href="/features" tabindex="2">Features</a>

This creates an artificial tab order that is hard to maintain. It can also confuse users because focus jumps around.

Better:

<a href="/pricing">Pricing</a>
<a href="/features">Features</a>
<a href="/contact">Contact</a>

Let the document order do the work. If the visual order and DOM order disagree, consider changing the DOM order rather than forcing focus order with tabindex.

Failure 4: Hidden content is still focusable

Sometimes a collapsed menu, offscreen drawer, or hidden modal contains focusable links. A keyboard user tabs into invisible content and loses track of where they are.

Problem:

<nav class="mobile-menu closed">
  <a href="/features">Features</a>
  <a href="/pricing">Pricing</a>
</nav>

If the menu is visually hidden only with positioning, its links may still receive focus.

Better:

<nav id="mobile-menu" hidden>
  <a href="/features">Features</a>
  <a href="/pricing">Pricing</a>
</nav>

When the menu is closed, use hidden, display: none, or the inert attribute where appropriate so the links are not focusable. When opened, restore visibility and move focus intentionally if needed.

Failure 5: Modals trap focus incorrectly

A modal dialog should keep focus inside the modal while it is open, but it should not trap the user permanently. A good modal should:

A simplified pattern:

<button type="button" id="open-dialog">
  Open settings
</button>

<div
  id="settings-dialog"
  role="dialog"
  aria-modal="true"
  aria-labelledby="settings-title"
  hidden
>
  <h2 id="settings-title">Settings</h2>
  <button type="button" id="close-dialog">Close</button>
  <label for="display-name">Display name</label>
  <input id="display-name" type="text">
</div>

When building complex modals, do not rely on visual appearance alone. Test with the keyboard from open to close.

How to fix keyboard accessibility step by step

Step 1: Use semantic HTML first

Start by replacing custom clickable elements with native controls. Use:

<button>
<a>
<input>
<select>
<textarea>
summary/details

Avoid building custom controls unless there is a real reason. Native HTML controls come with built-in keyboard behavior. A button works with keyboard activation. A link receives focus. A checkbox toggles with Space. A select supports keyboard interaction. These defaults are often better than custom JavaScript.

Step 2: Make every interactive element reachable

Tab through the page from the browser address bar. Every interactive element should be reachable unless it is intentionally disabled or hidden. Check:

If a control can be clicked, it should usually be keyboard reachable.

Step 3: Make activation work with the keyboard

Reaching an element is not enough. The user also needs to activate it. Links should activate with Enter. Buttons should activate with Enter and Space. Checkboxes should toggle with Space. Custom widgets should follow expected keyboard patterns.

If you add JavaScript only to click, a native button will still usually work because keyboard activation triggers click behavior. But if you use non-native controls, you may have to manually handle key events. That is another reason to prefer native controls.

Step 4: Fix focus visibility

A keyboard user must be able to see where focus is. Do not remove outlines without replacing them.

Bad:

*:focus {
  outline: none;
}

Better:

:focus-visible {
  outline: 3px solid currentColor;
  outline-offset: 3px;
}

You can customize focus styles to fit your brand, but they must remain visible.

Step 5: Keep focus order logical

Focus order should match the task. A user should not jump from the header to the footer, then back to a sidebar, then into the main content. Avoid positive tabindex. Use tabindex="-1" only when you need to programmatically move focus to an element, such as a modal heading or error summary.

<h2 id="form-errors" tabindex="-1">
  Please fix the following errors
</h2>

Then JavaScript can move focus there after a failed form submission:

document.getElementById("form-errors").focus();

Step 6: Prevent keyboard traps

Try to enter and exit every interactive region. If you open a modal, can you close it? If you open a menu, can you move past it? If a third-party calendar widget opens, can you leave it? Keyboard traps often appear in:

If a third-party widget traps focus, check whether it has an accessible configuration, updated version, or alternative implementation.

Manual keyboard test

Use this simple test on every important page.

  1. Load the page.
  2. Put your mouse aside.
  3. Press Tab.
  4. Confirm that a visible focus indicator appears.
  5. Continue pressing Tab.
  6. Confirm focus moves in a logical order.
  7. Activate links and buttons with Enter.
  8. Activate buttons and checkboxes with Space.
  9. Open and close menus.
  10. Open and close modals.
  11. Complete forms.
  12. Submit the form.
  13. Confirm errors are reachable and understandable.
  14. Use Shift + Tab to move backward.
  15. Confirm you never get trapped.

If you cannot complete the main user task with the keyboard alone, the page needs work.

How ADA CodeFix helps

ADA CodeFix can flag many keyboard-related patterns, including:

Automated checks are useful for finding likely problems, but they cannot fully confirm keyboard usability. A page can pass many automated checks and still have a confusing focus order or a custom widget that behaves poorly. Manual keyboard testing remains essential.

Common mistakes to avoid

Removing outlines globally

Designers sometimes remove outlines because the default browser outline looks plain. That creates a major usability problem. Do not do this:

button:focus,
a:focus,
input:focus {
  outline: none;
}

Replace it with a visible focus style.

Using tabindex to force the page order

Positive tabindex values are usually a maintenance problem. They create a separate focus order that can break as soon as content changes.

Making disabled controls focusable without explanation

If a button is disabled, users need to understand why. Sometimes it is better to keep the button enabled and show validation messages, or provide nearby instructions explaining what is required.

Opening popups without moving focus

If a modal opens but focus stays behind it, keyboard users may continue tabbing through the background page without realizing a dialog appeared.

Closing modals without returning focus

When a modal closes, focus should usually return to the button that opened it. Otherwise the user may be placed at the top of the page or lose their location.

Platform-specific notes

WordPress

Check navigation menus, popups, cookie banners, page-builder accordions, and forms. Many accessibility issues come from plugins. If a plugin creates a custom menu or modal, test it with the keyboard before relying on it.

Shopify

Test product image galleries, size selectors, variant dropdowns, cart drawers, discount fields, checkout-adjacent forms, and email signup popups. Cart drawers and product sliders are common keyboard trouble spots.

Webflow

Webflow sites can be keyboard accessible, but custom interactions should be tested carefully. Menus, tabs, sliders, and modals may need extra attention.

React and Next.js

Use semantic components. Avoid creating clickable divs. If you build custom components, manage focus intentionally and test with the keyboard. Use established accessible libraries for complex widgets when possible.

Final takeaway

Keyboard accessibility is not an edge case. It is a basic measure of whether a website can be operated by people who do not use a mouse. Many keyboard issues come from custom UI patterns that look good visually but ignore native browser behavior. The safest approach is simple: use semantic HTML, keep focus visible, avoid positive tabindex, make menus and modals keyboard friendly, and manually test the main user flows.

ADA CodeFix can help identify likely issues and generate developer-reviewable fixes, but the final test is practical: can someone complete the task with the keyboard alone?

Sources

Run a free WCAG 2.1 AA scan on your site

ADA CodeFix scans your pages, identifies likely keyboard, focus, and ARIA failures, and generates developer-reviewable code fixes you can ship.

Scan My Site Free