Fixing Missing and Hidden Focus Indicators
The focus indicator is the outline or highlight that shows which link, button or field will respond when a keyboard user presses Enter or starts typing. People who cannot use a mouse, including many with motor impairments and all screen reader users who can see the screen, rely on it the way others rely on the mouse pointer.
Designers often remove it because it appears on mouse clicks. This guide shows how to find where it was removed, restore it with :focus-visible so mouse users are not bothered, make it visible on any background, and keep it from hiding behind sticky bars.
The WCAG criteria behind focus findings
Three success criteria in WCAG 2.2 deal directly with focus, and one more affects how visible the indicator must be.
| Criterion | Level | In plain English |
|---|---|---|
| 2.4.7 Focus Visible | AA | When you use the keyboard, you can always see which element has focus. |
| 2.4.11 Focus Not Obscured (Minimum) | AA, new in 2.2 | The focused element is not completely hidden by content the site added, such as a sticky header, cookie banner or chat widget. |
| 2.4.12 Focus Not Obscured (Enhanced) | AAA | No part of the focused element is hidden. |
| 2.4.13 Focus Appearance | AAA | The indicator is at least as large as a 2 CSS pixel thick perimeter and changes contrast by at least 3:1 between focused and unfocused states. |
Level AA does not set a minimum size or contrast for the indicator itself; 2.4.7 only requires that it is visible. In practice a one-pixel dotted line in a pale colour is hard to argue is visible, and 1.4.11 Non-text Contrast is commonly applied to focus indicators too. Aiming at the AAA Focus Appearance measure, a solid outline at least 2px thick with at least 3:1 contrast against its surroundings, is a sensible target that clears AA comfortably.
Why focus outlines go missing
Browsers draw a focus ring by default. It disappears for a small number of reasons, and the checker's finding usually traces back to one of them:
- A reset or theme rule such as
*:focus { outline: none; }. Often added years ago to stop the ring appearing when buttons are clicked, and never replaced with anything. - A framework utility. Classes such as Tailwind's outline utilities or custom
.no-outlineclasses applied to buttons and links across a component library. - A focus style with too little contrast. A thin light blue ring on a light blue header, or a white ring on a white card, technically exists but cannot be seen.
- Focus drawn with
box-shadowonly. This looks fine normally but disappears in Windows contrast themes and other forced colours modes, because box shadows are not drawn there. overflow: hiddenon a parent. An outline drawn outside the element's box is clipped by a container, typically in carousels, cards and menus.- Sticky and fixed elements. The item has focus and a visible outline, but a sticky header, footer, cookie banner or chat button sits on top of it.
The fix, step by step
Step 1
Tab through the page and note gaps
Click in the browser address bar, then press Tab repeatedly through the whole page, including the header, menus, forms, footer and any cookie banner. Write down every point where you lose track of where focus is, where the indicator is faint, and where a focused item is covered by something. On a Mac using Safari, first turn on the setting that lets Tab highlight each item on a web page, otherwise Tab skips links. Compare your notes with the Accessibility Audit findings.
Step 2
Find the CSS that removes the outline
Inspect
an element that shows no ring, then use the developer tools to force its state to focus or focus-visible
in the Styles pane. Look for rules setting outline: none, outline: 0 or outline-style: none
and note the file and selector they come from. Also search your stylesheets, theme files and component
code for those values. Remove global resets that strip outlines from every element, rather than overriding
them again later in the cascade.
Step 3
Add a clear :focus-visible style
Add
one site-wide rule using :focus-visible, which browsers apply when focus comes from the
keyboard and usually not after a mouse click on a button. A solid outline at least 2px thick, offset
slightly from the element with outline-offset, is simple and robust. Choose a colour with
at least 3:1 contrast against the background around the element. Keep text inputs showing focus even
after a mouse click, which browsers already do for fields under :focus-visible.
Step 4
Make the indicator work on every background
If your site mixes light and dark areas, such as a dark header, white content and a
coloured footer, one outline colour may vanish somewhere. Either set a different outline colour inside
dark sections, or use a two-tone indicator: a dark outline with a light inner ring created by box-shadow,
so one of the two colours always contrasts. Check the indicator against photos and coloured buttons,
and remove overflow: hidden clipping or use a negative offset where needed.
Step 5
Style custom controls and skip links
Check elements the global rule may miss: custom checkboxes and radio buttons that hide the
real input, toggle switches, tabs, accordion headers, slider handles and card links. When the real input
is visually hidden, show focus on its visible replacement with a selector such as input:focus-visible + .fake-box.
Make sure the skip to content link becomes visible on focus rather than staying off screen, and that
it has the same clear indicator.
Step 6
Stop sticky bars covering focused items
For a sticky header, add scroll-padding-top to the html element
equal to the header height, so the browser scrolls focused items clear of it; use scroll-padding-bottom
for sticky footers and bottom bars. Make cookie banners and pop-ups either take focus themselves until
dismissed, or sit where they do not cover content. Chat buttons fixed in a corner should not overlap
links in the footer at common screen sizes.
Step 7
Test with the keyboard and forced colours
Tab through the whole page again and confirm you can always see where focus is, on every background and with nothing covering it. Repeat at a narrow mobile width and at 200 percent zoom, where sticky headers take up more of the screen. In Chrome or Edge developer tools, open the Rendering panel and emulate forced colours to check the indicator survives. Then run the Accessibility Audit again on each changed template.
Focus CSS you can adapt
A site-wide default
/* Remove any old global reset such as *:focus { outline: none; } */
:focus-visible {
outline: 3px solid #1d4ed8;
outline-offset: 2px;
}
/* Inside dark areas, switch to a light outline */
.site-header :focus-visible,
.site-footer :focus-visible {
outline-color: #fbbf24;
}
Using outline rather than border means the indicator does not change the
element's size or push the layout around. Outlines follow border-radius in all current major
browsers, so rounded buttons get rounded rings.
A two-tone indicator for mixed backgrounds
:focus-visible {
outline: 3px solid #111827;
outline-offset: 2px;
box-shadow: 0 0 0 2px #ffffff;
}
The white shadow sits inside the dark outline, so the indicator shows against both light and dark surroundings. In forced colours mode the shadow is dropped, but the outline remains and the system picks a suitable colour for it.
Keeping a ring in forced colours when you design with shadows
.btn:focus-visible {
outline: 2px solid transparent; /* invisible normally, shown in forced colours */
box-shadow: 0 0 0 3px #1d4ed8;
}
A transparent outline is invisible in normal viewing, but in forced colours mode the browser replaces the colour and draws it, so keyboard users in a contrast theme still see focus.
Sticky header clearance
html {
scroll-padding-top: 5rem; /* at least the height of the sticky header */
scroll-padding-bottom: 4rem; /* if there is a sticky bottom bar */
}
Themes, page builders and frameworks
WordPress. Many older themes include an outline reset in style.css.
Add the replacement rules in a child theme stylesheet or in Appearance, Customize, Additional CSS for
classic themes, or in the Styles panel's custom CSS for block themes. Page builders sometimes apply their
own reset to buttons and menu items, so test builder pages separately. Cookie consent plugins are a frequent
cause of 2.4.11 failures; check their position settings.
Shopify. Recent themes generally include focus styles, but customisations, app blocks and older themes may strip them. Add fixes to the theme's main stylesheet through the code editor, or to a custom CSS setting where the theme offers one, and test the header drawer menu, cart drawer and product option selectors in particular.
Tailwind CSS. Search for outline-none and focus:outline-none
in your markup and make sure each is paired with a visible focus-visible: style, such as
an outline or ring. Tailwind's ring utilities are built with box-shadow, so they disappear in forced
colours unless a transparent outline is also present. Tailwind version 4 changed how its outline utilities
behave, with outline-hidden now keeping a transparent outline for forced colours; check
the documentation for the version you use.
Bootstrap and component libraries. Many libraries draw focus rings with box-shadow in a semi-transparent brand colour. Check the contrast of that ring against your backgrounds and add an outline for forced colours if needed. For JavaScript apps where focus moves between views, see the React and Next.js accessibility guide.
Situations that need extra care
- Focus moved by script. When a modal opens or a single-page app changes view, code
often moves focus with
element.focus(). Browsers decide whether to show:focus-visiblebased on how the user was interacting; test both keyboard and mouse paths so focus is visible for keyboard users. - Headings and containers given
tabindex="-1". These receive focus only from scripts, for example after a skip link. Showing an outline on a whole section can look odd; a subtle but visible indicator is acceptable, but do not hide it completely. - Carousels and horizontal scrollers. Focus can move to slides that are scrolled out of view. Make sure the carousel scrolls to the focused item, or hide off-screen slides from the tab order.
- Elements that should not be focusable. If Tab lands on something invisible or pointless, the fix is in the tab order, which is covered in fixing keyboard navigation, not in the focus style.
- Brand-coloured rings. A focus ring in the brand colour is fine if it has enough contrast. If it does not, use a darker variant; the colour contrast guide explains how to create one.
Keeping focus visible after redesigns
- Keep one focus rule in a base stylesheet and ban global outline resets in code review.
- Include focus states in design files and component libraries, next to hover and active states, so designers approve them rather than removing them.
- Add a keyboard pass to every release: Tab through the home page, a product or service page and the contact form.
- Recheck cookie banners, chat widgets and sticky bars whenever a new plugin, app or script is added.
- Run the Accessibility Audit after theme updates, because updates can reintroduce resets.
1. Why did my designer remove the focus outline?
Usually because browsers used to show the ring when someone clicked a button with the mouse, which looked like a bug to people who never use a keyboard. The quick fix at the time was outline none, which removed it for everyone. The :focus-visible selector solves the original complaint properly: browsers show it for keyboard focus and usually not after a mouse click on a button. So you can have a clean look for mouse users and a clear indicator for keyboard users.
2. Is outline: none always an accessibility failure?
Not by itself. Removing the default outline is fine if you replace it with another clearly visible focus style, such as a thick border, an underline, a background change or a custom outline. The failure is removing it and putting nothing in its place, or replacing it with something too faint to see. When you review code, treat every outline none as a question: where is the replacement style, and does it have enough contrast against the background around it?
3. What should a good focus indicator look like?
A solid outline around the element, at least two pixels thick, in a colour with at least three to one contrast against the surrounding background, and slightly offset so it does not merge with the element's own border. That meets the WCAG 2.2 AAA Focus Appearance measure, which is a useful target even though level AA only asks for visibility. It should be consistent across the site, so users learn what focus looks like once and can recognise it everywhere.
4. What does Focus Not Obscured mean?
It is a WCAG 2.2 success criterion, 2.4.11 at level AA, which says that when an element receives keyboard focus it must not be completely hidden by content the site has added, such as a sticky header, sticky footer, cookie banner or chat widget. The level AA version allows partial overlap; the AAA version, 2.4.12, does not. The usual fixes are scroll padding equal to the height of sticky bars, and banners that do not float over page content.
5. Do I need focus styles if my site has no forms?
Yes. Every link, button, menu toggle, accordion and embedded video player can receive keyboard focus, and keyboard users need to see where they are on every page, not only on forms. A brochure site with a navigation menu, a few calls to action and a footer full of links still needs a visible indicator on all of them. The good news is that one site-wide focus-visible rule usually covers most of those elements at once.
6. Why can I not see focus in Safari when I press Tab?
By default Safari on macOS moves Tab only between form fields, not links and buttons. To test properly, turn on the Safari setting that makes Tab highlight each item on a web page, or use Option and Tab. Some Mac users also enable keyboard navigation in the system settings. This is a browser setting, not a problem with your site, but it catches out many people testing focus styles for the first time on a Mac.
7. Will a focus outline spoil my design?
It does not need to. Choose a colour from your palette with enough contrast, use a consistent thickness and offset, and match the outline to rounded corners, which current browsers do automatically. Because :focus-visible usually hides it for mouse clicks, most visitors will rarely see it, while keyboard users will always get it. Many design systems treat a well designed focus ring as part of the brand, alongside the hover and active states.
The Accessibility Audit tests your page against WCAG 2.2 level AA and lists each finding with the element that failed and the success criterion behind it, so you can see where focus styles need attention.
Open Accessibility Fixes โ