View contents
Focus Indicators: Making Keyboard Navigation Visible
Introduction
Focus indicators are visual cues that show which interactive element on a page currently has keyboard focus. They’re essential for users who navigate websites without a mouse—including people using keyboards, switch devices, or screen readers. WCAG 2.4.7 requires that focus indicators be visible, making them a fundamental accessibility requirement.
Without clear focus indicators, keyboard users can’t tell where they are on the page, making navigation essentially impossible. This affects millions of users who rely on keyboard navigation due to motor disabilities, visual impairments, or personal preference.
What Are Focus Indicators?
The Default Browser Focus
Browsers provide default focus indicators for interactive elements:
/* Default focus styles vary by browser */
:focus {
outline: auto; /* Chrome: blue outline */
outline: dotted 1px; /* Firefox: dotted */
outline: solid 2px; /* Safari: blue ring */
}
Interactive Elements That Receive Focus
| Element Type | Examples | Receives Focus |
|---|---|---|
| Links | <a href> |
Yes |
| Buttons | <button>, <input type="button"> |
Yes |
| Form Controls | <input>, <select>, <textarea> |
Yes |
| Custom Controls | tabindex="0" elements |
Yes |
| Non-Interactive | <div>, <span>, <p> |
No (by default) |
Why Focus Indicators Matter
Who Benefits
- Keyboard-only users - Must see where they are navigating
- Motor disability users - May use switch devices or alternative inputs
- Low vision users - Combine keyboard with screen magnification
- Power users - Prefer keyboard shortcuts for efficiency
- Temporary situations - Broken mouse, touchpad issues
The Navigation Problem
Without visible focus:
- Users can’t tell which link will activate when pressing Enter
- Form navigation becomes guesswork
- Skip links become invisible
- Users may accidentally activate wrong elements
WCAG Requirements
| Criterion | Level | Requirement |
|---|---|---|
| 2.4.7 Focus Visible | AA | Focus indicator must be visible |
| 2.4.11 Focus Not Obscured | AA | Focus can’t be fully hidden (WCAG 2.2) |
| 2.4.12 Focus Not Obscured (Enhanced) | AAA | Focus must be fully visible (WCAG 2.2) |
Common Focus Problems
1. Removed Focus Outlines
/* BAD: Removes focus for all users */
*:focus {
outline: none;
}
/* BAD: Also hides focus */
a:focus,
button:focus {
outline: 0;
}
This is often done because designers find the default outline “ugly,” but it creates a significant accessibility barrier.
2. Low Contrast Focus Indicators
/* BAD: Focus barely visible */
button:focus {
outline: 1px solid #ddd;
}
/* BAD: Focus blends with background */
.dark-section a:focus {
outline: 2px solid #333;
}
3. Focus Hidden by Other Elements
/* BAD: Sticky header covers focused elements */
.header {
position: sticky;
top: 0;
z-index: 100;
}
/* No scroll margin = focus hidden behind header */
4. Focus Only on Mouse Hover
/* BAD: Visual feedback only for mouse */
button:hover {
background: #007bff;
}
/* No :focus state = keyboard users left out */
The :focus-visible Solution
Modern CSS provides :focus-visible, which shows focus only for keyboard navigation:
/* Remove focus ring for mouse users */
button:focus {
outline: none;
}
/* Show focus ring only for keyboard users */
button:focus-visible {
outline: 3px solid #007bff;
outline-offset: 2px;
}
How :focus-visible Works
| Interaction | :focus | :focus-visible |
|---|---|---|
| Mouse click | ✅ Triggers | ❌ Doesn’t trigger |
| Tab key | ✅ Triggers | ✅ Triggers |
| Arrow keys | ✅ Triggers | ✅ Triggers |
| Touch tap | ✅ Triggers | ❌ Doesn’t trigger |
This provides the best of both worlds:
- Keyboard users see clear focus indicators
- Mouse users don’t see outlines after clicking
Quick Design Guidelines
Effective Focus Indicators
- High contrast - 3:1 minimum against adjacent colors
- Sufficient size - At least 2px outline or clear visual change
- Consistent style - Same treatment across the site
- Not obscured - Visible even with sticky headers
Good Focus Indicator Examples
/* Solid outline with offset */
:focus-visible {
outline: 3px solid #005fcc;
outline-offset: 2px;
}
/* Box shadow approach */
:focus-visible {
outline: none;
box-shadow: 0 0 0 3px rgba(0, 95, 204, 0.5);
}
/* Background change */
:focus-visible {
background-color: #fff3cd;
outline: 2px solid #856404;
}
Testing Focus Indicators
Quick Manual Test
- Put your mouse aside
- Press Tab repeatedly through the page
- Can you see where focus is at all times?
- Can you tell which element will activate on Enter?
- Is focus ever hidden behind sticky elements?
Common Test Points
- Navigation links
- Buttons and CTAs
- Form fields
- Skip links
- Modal close buttons
- Dropdown triggers
Tools That Help
- Browser DevTools - Force focus state on elements
- axe DevTools - Detects focus indicator issues
- WAVE - Highlights focus order problems
- Keyboard only - Best test is real keyboard navigation
Best Practices Summary
| Do | Don’t |
|---|---|
| Keep or enhance default focus styles | Remove outline with outline: none |
Use :focus-visible for clean UX |
Apply :focus and :hover identically |
| Ensure 3:1 contrast ratio | Use low contrast focus indicators |
| Add scroll margin for sticky headers | Let focus hide behind fixed elements |
| Test with keyboard navigation | Assume mouse testing is enough |
Related Articles
- Focus Indicators Implementation Guide - Detailed techniques
- Keyboard Navigation Guide - Full keyboard accessibility
- WCAG Compliance Hub - All accessibility evaluators
References
- W3C - WCAG 2.2 SC 2.4.7 Focus Visible
- W3C - WCAG 2.2 SC 2.4.11 Focus Not Obscured
- WebAIM - Keyboard Accessibility
- MDN - :focus-visible pseudo-class