Keyboard Accessibility: The Most Overlooked UX Requirement

Floating Tab key with radiating focus navigation paths

Somewhere in your CSS right now, there's a line that says *:focus { outline: none; }. Maybe you put it there. Maybe a CSS reset did. Maybe a former developer added it because a client said the blue ring "looked weird." That single line of code just made your website unusable for everyone who doesn't use a mouse.

That's not hyperbole. WCAG 2.1 Success Criterion 2.4.7 (Focus Visible) is a Level AA requirement, meaning it applies to any site claiming accessibility compliance. Removing the focus outline without providing a replacement violates it outright. And this is one of the most common accessibility failures on the web, partly because the people making the decision never test their sites without a mouse.

Who Actually Uses a Keyboard to Browse the Web

The instinct is to think "keyboard users" means "blind people." It doesn't. Blind users rely on screen readers, which do depend on keyboard access, but the population of keyboard-dependent users is far wider than most developers realize.

People with motor impairments who can't grip or control a mouse. People with repetitive strain injuries from years of mouse-heavy work. People with tremors, limited fine motor control, or paralysis affecting one or both hands. People recovering from surgery on their wrist, shoulder, or arm. People using switch devices, sip-and-puff controls, or head-tracking systems that all map to keyboard input under the hood.

Then there are the people who simply prefer it. Power users who live in keyboard shortcuts. Developers who consider reaching for a mouse a sign of inefficiency. Data entry workers who tab through forms hundreds of times a day.

A 2013 WebAIM survey found that 35% of users with motor disabilities rely on the keyboard as their primary input device. Almost two million Americans experience repetitive strain injuries annually, and many of them shift away from mouse use during recovery. Add temporary injuries, situational limitations (try using a laptop trackpad on a train), and personal preference, and the number of people affected by keyboard accessibility failures grows well beyond the disability community.

None of this is theoretical. These are people trying to use your website right now. If the Tab key does nothing visible on your site, they leave.

The Three Failures That Break Everything

Most keyboard accessibility problems fall into three categories. Each one has a specific WCAG success criterion attached to it, and each one is fixable with straightforward code changes.

Invisible Focus Indicators

This is the one we feel strongest about, so we'll say it plainly: removing the default focus outline is an act of negligence, not a design decision.

The browser's default focus ring exists for the same reason a cursor exists on screen. It tells you where you are. When a developer removes it with outline: none or outline: 0 and provides no alternative, they've erased the visual cue that keyboard users depend on to know which element they're interacting with. WebAIM has called this pattern a "plague" and it remains one of the most widespread accessibility violations across the web.

WCAG 2.1 SC 2.4.7 (Focus Visible) requires that keyboard focus indicators be visible. WCAG 2.2 goes further with SC 2.4.11 (Focus Not Obscured) at Level AA, requiring that the focused element isn't completely hidden behind sticky headers, cookie banners, or other layered content. SC 2.4.13 (Focus Appearance) at Level AAA specifies minimum size and contrast requirements for the indicator itself: at least a 3:1 contrast ratio against adjacent colours, with a minimum area equivalent to a 2px thick perimeter around the element.

The fix is not complicated. The :focus-visible CSS pseudo-class, supported in all modern browsers since March 2022, shows the focus indicator only when the user is actually navigating by keyboard. Mouse clicks don't trigger it. This solves the exact complaint that drove developers to remove outlines in the first place.

/* Remove the default outline for mouse users */
:focus:not(:focus-visible) {
  outline: none;
}
/* Style keyboard focus clearly */
:focus-visible {
  outline: 2px solid #247060;
  outline-offset: 3px;
}

That's it. Two rules. Your designer gets a clean interface for mouse users. Your keyboard users get a visible indicator. The W3C's own technique document C45 recommends exactly this approach.

One thing to watch: box-shadow is a popular substitute for outlines, but it vanishes entirely in Windows High Contrast Mode. If you rely on box-shadow alone for focus styles, users running high contrast themes see nothing. Always keep an outline property in the chain, even if you set it to transparent for normal display. High Contrast Mode forces outlines to be visible regardless of the colour you set.

Focus Traps

A focus trap is what happens when a keyboard user tabs into a component and can't tab back out. The most common culprit is a poorly coded modal dialog or popup. You open a newsletter signup modal, you tab through the fields, and when you hit Tab after the last field, focus jumps back to the first field instead of returning to the page behind it. Or worse, focus leaves the modal entirely and wanders behind it where you can't see what's happening.

WCAG 2.1 SC 2.1.2 (No Keyboard Trap) is a Level A requirement. Level A. That's the absolute baseline of accessibility compliance. If your site traps keyboard focus, it fails the most basic tier of WCAG.

The correct behaviour for a modal dialog is specific. When the modal opens, focus moves into it. Tab cycles through the focusable elements inside the modal and wraps from last to first. Shift+Tab wraps from first to last. Pressing Escape closes the modal. When the modal closes, focus returns to the element that triggered it.

The HTML <dialog> element handles most of this natively in modern browsers. If you're building custom modals with <div> elements, you're taking on the responsibility of managing all of this yourself, and most implementations get at least one part wrong.

<!-- The native dialog element handles focus management -->
<dialog id="signup-modal" aria-labelledby="modal-title">
  <h2 id="modal-title">Sign up for updates</h2>
  <form method="dialog">
    <label for="email">Email address</label>
    <input type="email" id="email" required>
    <button type="submit">Subscribe</button>
    <button type="button" onclick="this.closest('dialog').close()">
      Cancel
    </button>
  </form>
</dialog>

If you must build a custom focus trap (for a complex widget or older browser support), the pattern involves tracking all focusable elements inside the container and intercepting Tab and Shift+Tab keypresses to loop focus within the boundaries. But we'd push back on that approach in almost every case. Use <dialog>. Let the browser do the work.

Dropdown menus, date pickers, and autocomplete fields are the other frequent offenders. Third-party libraries are often the source of the problem. If you install a jQuery datepicker or a React dropdown component, test it with a keyboard before you ship it. Tab into it, interact with it, and Tab out. If you get stuck, your users will too.

Unreachable Elements

The third category is elements that simply don't receive focus at all. Custom-styled <div> and <span> elements that act as buttons but aren't coded as buttons. Click handlers on elements that have no keyboard equivalent. Interactive components that respond to mouse hover but have no focus state.

WCAG 2.1 SC 2.1.1 (Keyboard) is Level A. All functionality must be operable through a keyboard interface. No exceptions for "but it looks like a button."

The root cause is almost always the same: a developer used the wrong HTML element. A <div onclick="doSomething()"> looks like a button on screen but doesn't appear in the tab order, doesn't respond to Enter or Space, and isn't announced as a button by screen readers. The fix is to use a <button> element. It's focusable by default, responds to keyboard activation by default, and is announced correctly by default.

When you genuinely need a non-interactive element to receive focus (a custom widget, a dynamically updated region), tabindex is the tool. But it's often misused.

<!-- tabindex="0": adds element to natural tab order -->
<div role="button" tabindex="0" onclick="doSomething()"
     onkeydown="if(event.key==='Enter'||event.key===' ')doSomething()">
  Click me
</div>
<!-- tabindex="-1": focusable via JavaScript only, not via Tab -->
<div id="error-message" tabindex="-1" role="alert">
  Something went wrong.
</div>
<!-- tabindex with positive values: NEVER do this -->
<!-- It overrides the natural document order and creates chaos -->

Positive tabindex values (1, 2, 3, etc.) create an explicit tab order that overrides the document's natural flow. Every major accessibility resource, from WebAIM to Deque University to the W3C, recommends against using them. They're fragile, hard to maintain, and almost always produce a worse experience than the default order.

The better approach is always to fix the document structure so the natural tab order makes sense, then use tabindex="0" sparingly for custom interactive elements and tabindex="-1" for programmatic focus management.

If your site can't be used without a mouse, it can't be used. Full stop. Keyboard access isn't a bonus feature or an edge case consideration. It's a requirement baked into the most basic level of WCAG conformance, and ignoring it excludes real people from your product.

How to Test Keyboard Accessibility in 10 Minutes

You don't need special tools for this. You need a keyboard and the willingness to put your mouse in a drawer for 10 minutes.

Keyboard Accessibility Quick Test

  1. Press Tab from the top of your page. A visible indicator should appear on the first interactive element (ideally a skip link). Keep tabbing. Can you see where focus is at every step?

  2. Tab through your entire navigation menu. Can you open submenus with Enter or Space? Can you close them with Escape? Does focus return to the parent menu item after closing?

  3. Tab to every button and link on the page. Press Enter on each one. Do they all work? Do any elements respond to mouse clicks but not to keyboard activation?

  4. Open every modal, popup, and dropdown. Can you close each one with Escape? Does focus return to the trigger? While the modal is open, does Tab stay inside it or does it wander behind to the page?

  5. Fill out every form on your site. Tab between fields. Can you select dropdown options with arrow keys? Can you check checkboxes with Space? Can you submit with Enter?

  6. Check for focus traps. If at any point you can't move forward or backward with Tab and Shift+Tab, you've found one. Document where it happens.

  7. Look at the focus indicator itself. Is it visible against every background colour on your site? A dark outline works on a light background but disappears on a dark section. Test both.

If your site passes all seven steps, it's in good shape for keyboard access. If it fails step one, you have work to do before anything else matters.

We outlined a broader set of accessibility tests in our accessibility checklist for business owners, and we covered why these structural issues can't be fixed with automated tools in our piece on why accessibility overlays don't work. Keyboard testing is one of the few accessibility checks that requires zero technical knowledge and reveals problems instantly.

Fixing It: A Practical Approach

The good news is that keyboard accessibility failures have clear, well-documented fixes. The bad news is that they require going through your codebase and touching every interactive element. There's no shortcut.

Start with a full keyboard audit. Tab through every page of your site and document every point where focus disappears, gets trapped, or doesn't reach an interactive element. Prioritize by severity: traps first (Level A violation, complete blocker), then missing focus indicators (Level AA, affects every keyboard user), then unreachable elements (Level A, blocks specific functionality).

Replace every <div> and <span> that acts as a button with an actual <button>. Replace every <div> that acts as a link with an actual <a href>. This single change often fixes 40-50% of keyboard accessibility issues because native HTML elements come with keyboard support built in.

Add :focus-visible styles to your global stylesheet. Audit your CSS for any instance of outline: none or outline: 0 that isn't immediately followed by an alternative focus style. Remove the bare removals. Keep the replacements.

Test every third-party component. Carousels, date pickers, lightboxes, dropdown menus, chat widgets, cookie consent banners. Third-party code is responsible for a disproportionate share of keyboard failures because developers tend to trust the library without testing it. Don't.

Replace custom modal implementations with the native <dialog> element where possible. For modals that must remain custom, implement the full focus management pattern: move focus in on open, trap focus inside, return focus on close, close on Escape.

When we build sites for clients, keyboard accessibility goes into the code from the first commit. It's dramatically cheaper to build it right than to remediate it later, and the structural discipline it requires produces better code across the board. Proper semantic HTML, a clear document flow, and correct use of native elements aren't just accessibility requirements. They're signs of professional-quality front-end work.

If you're not sure where your site stands, our guide to why accessibility matters covers the broader business case, and we're always happy to run a quick audit.

The keyboard test is the single most revealing accessibility check you can run. Ten minutes, no tools, no budget, no excuses. Put the mouse away and start pressing Tab. What happens next will tell you everything you need to know about how your site was built.


Sources

Get In Touch

Let's talk about your project.

Whether you have a clear scope or just a rough idea, we'd love to hear from you. Tell us what you need and we'll get back within one to two business days.

Not sure where to start? Take our 2-minute assessment and get a personalized recommendation before reaching out.

Rather see our thinking first? Include your current website in the form and we’ll review it before we reply — your response comes back with the three highest-impact things we’d fix, not a sales pitch. If you’d like to walk through them together after, we’re happy to.

Calgary, Alberta, Canada

Response within 1–2 business days

Tell us about your project

The more detail you share, the better we can understand how to help.