Keyboard focus: how to make sure people can see where they are (WCAG 2.4.7)
Updated October 26, 2026 · 10 min read
Short answer. Anyone using a keyboard needs a visible indicator of where focus is. Never remove the outline without replacing it, style it with :focus-visible at a contrast of at least 3 to 1, make sure sticky headers do not cover the focused item, and check that every control can be reached and left with the keyboard.
What the rules say
- 2.4.7 Focus Visible (AA): a keyboard focus indicator must be visible on every interface element that can receive focus.
- 2.4.11 Focus Not Obscured, Minimum (AA, new in WCAG 2.2): a focused item must not be completely hidden by other content, such as a sticky header or cookie banner.
- 2.1.2 No Keyboard Trap (A): if focus moves into something, it must be possible to move out using the keyboard.
- 2.4.3 Focus Order (A): focus moves in an order that preserves meaning.
The most common failure
/* Before: removes the browser's focus ring and replaces it with nothing (fails) */
a, button, input { outline: none; }
/* After: a clear, high-contrast ring only for keyboard focus */
:focus-visible {
outline: 3px solid #1a56db;
outline-offset: 2px;
}:focus-visible shows the ring for keyboard use and usually not after a mouse click, so you keep a clean look without losing the indicator. Aim for a ring with at least 3 to 1 contrast against the background and against the element, and make sure it works on both light and dark sections.
Sticky headers and banners
When you Tab down a long page, the focused link must not slide beneath a fixed header. Add scroll padding so the browser scrolls it into clear view.
html { scroll-padding-top: 5rem; } /* about the height of your sticky header */Popups, menus and carousels
- When a dialog opens, move focus into it, keep focus inside while it is open and return focus to the button that opened it when it closes.
- Escape should close menus and dialogs.
- Custom controls built from
divorspanneed to be focusable and respond to Enter and Space. A realbuttondoes this for free (names guide). - Avoid positive
tabindexvalues, which create confusing focus order.
Who uses a keyboard
People who are blind use the keyboard to move through pages with a screen reader. People with motor disabilities may use a keyboard, a switch or voice control that acts like a keyboard. People with a temporary injury, tremor or fatigue may find a mouse difficult. Power users prefer the keyboard because it is fast. Making a page work with the keyboard helps all of them, and it is a good test of whether your page is built correctly.
The keys to know
| Key | What it does |
|---|---|
| Tab | Moves to the next link, button or field |
| Shift + Tab | Moves to the previous one |
| Enter | Activates links and buttons |
| Space | Activates buttons, checks boxes and scrolls the page |
| Arrow keys | Move within groups such as radio buttons, menus and tabs |
| Escape | Closes popups, menus and dialogs |
Skip links
A skip link is the first focusable item on the page. It lets keyboard users jump past the header and navigation straight to the main content. It is usually hidden until it receives focus. Without it, a person who uses a keyboard must tab through every menu item on every page. WCAG requires a way to bypass repeated blocks (2.4.1), and a skip link is the simplest way to provide it.
<a class="skip" href="#main">Skip to main content</a>
...
<main id="main" tabindex="-1">...</main>
.skip { position: absolute; left: -999px; }
.skip:focus { left: 8px; top: 8px; background: #fff; padding: 8px; }Focus order and focus management
Focus should follow the logical order of the page, usually the order in which things appear. Problems appear when layout tricks move things on the screen without changing the order in the code. Dialogs need special care: when one opens, focus should move into it, stay inside until it closes and return to the button that opened it. When content is added or removed, such as in a cart drawer or a search suggestion list, think about where focus should go.
Custom controls
A native button or link comes with keyboard behavior built in. A div styled to look like a button does not. If you must build a custom control, give it a role, make it focusable, handle Enter and Space and expose its state. In most cases, using the right HTML element is simpler and more reliable than adding code to fix the wrong one.
Fixing the focus outline
:focus-visible {
outline: 3px solid #1a56db;
outline-offset: 2px;
}
/* Never: outline: none without a replacement */The outline should have at least 3 to 1 contrast against its surroundings. A dark outline with a light halo works on both light and dark backgrounds. WCAG 2.2 also asks that a focused item is not completely hidden by other content such as a sticky header (2.4.11).
Menus, carousels, tabs and accordions
| Component | Expected keyboard behavior |
|---|---|
| Dropdown navigation | Enter or Space opens a submenu, arrow keys or Tab move through items, Escape closes and returns focus to the trigger |
| Tabs | Arrow keys move between tabs, Tab moves into the active panel |
| Accordion | Enter or Space opens and closes a section, and the button announces whether it is expanded |
| Carousel | Previous and next buttons can be focused, and there is a way to pause automatic movement |
| Modal dialog | Focus moves into the dialog, stays inside, and returns to the trigger when closed |
| Tooltip | Appears on focus as well as hover, and can be dismissed with Escape |
Mouse-only features
Some features are built only for hovering or clicking. A menu that opens when the mouse passes over it cannot be opened with a keyboard unless extra code is added. A custom slider that responds only to dragging cannot be adjusted by someone who cannot drag. Look for drag and drop, hover menus, double-click actions and right-click menus, and make sure there is another way to do the same thing. WCAG 2.2 adds a specific criterion for dragging (2.5.7).
Testing methods that go beyond a quick tab-through
- Tab forwards and backwards through the whole page. Count the stops. If a page has 200 tab stops, a skip link and better structure may help.
- Watch for invisible focus. If you press Tab and nothing appears to change, you have found a missing indicator or a hidden element.
- Use the keyboard for every action. Open and close each menu, popup and accordion.
- Check for focus jumping. Focus should not move by itself, except when you open a dialog or submit a form.
- Check modals. Press Tab many times; focus should stay inside until the dialog closes.
- Test on a phone with an external keyboard, if you can, since some mobile layouts behave differently.
Fixing the common causes
- Replace clickable divs with buttons or links.
- Remove positive tabindex values, which override the natural order.
- Restore the focus outline and give it good contrast.
- Add a skip link and landmarks.
- Return focus to the trigger when a popup closes.
- Make sure hidden content is not focusable. Menus that are visually closed should not trap focus in the background.
A worked example: a store's cart drawer
A store opens the cart in a side drawer when someone presses "Add to cart". A sighted mouse user sees the drawer slide in. A keyboard user sees nothing change, because focus stays on the Add button while the drawer appears behind a dark overlay. Pressing Tab moves through the page underneath, and the user cannot reach Checkout without tabbing through the whole product page.
The fix has four parts. Move focus to the drawer heading when it opens. Keep focus inside while it is open. Close it with Escape. Return focus to the Add button when it closes. Add a visible focus style on every control in the drawer. With these changes the drawer is usable by keyboard, and it is easier for screen reader users, because they hear that a dialog has opened.
Typical focus problems on stores and how often they appear
| Problem | Where | Fix |
|---|---|---|
| Focus outline removed | Whole theme | Restore a custom focus style |
| Mega menu opens on hover only | Header | Open on focus and click as well |
| Cookie banner traps focus or sits unreachable | Bottom or top of page | Make it a proper region that can be reached and dismissed |
| Quick-view modal does not return focus | Collection pages | Return focus to the trigger on close |
| Image gallery arrows are not focusable | Product page | Use buttons with names |
| Hidden duplicate links | Mobile menu | Hide closed content from keyboard and screen readers |
What to tell your developer
Give them the sequence you followed and where it broke. For example: "Open the product page, press Tab until you reach Add to cart, press Enter. The drawer opens but focus stays behind it." A clear description like this saves time. Add what you expect to happen. Developers often fix keyboard problems quickly when they can see them.
Your questions about keyboard focus
- Why does my site look cleaner without the outline? The outline is the only signal that tells a keyboard user where they are. A cleaner design is possible with a thoughtful custom style.
- How do I find what is receiving focus? In the browser console, type document.activeElement after pressing Tab. Some developer tools also highlight the focused element.
- Do touch devices need focus styles? Phones with external keyboards and switch devices use focus, so keep the styles even if most people use touch.
- What is tabindex for? tabindex="0" makes an element focusable in the natural order, and tabindex="-1" makes it focusable by script only. Avoid positive values.
- Should every element be focusable? No. Only interactive elements need focus. Making static text focusable adds clutter.
Checklist
- A skip link appears on first Tab.
- Every link, button and field receives focus in a logical order.
- Focus is always visible, with at least 3 to 1 contrast.
- Menus, dialogs and popups can be opened and closed with the keyboard.
- Focus never gets trapped, and it returns to a sensible place after a dialog closes.
- Sticky bars do not hide the focused item.
If you can complete your main tasks with these seven steps passing, your site is in good shape for keyboard users.
Single-page apps and route changes
In a single-page application, moving to a new view does not reload the page, so screen reader and keyboard users receive no signal that the content has changed. When the route changes, update the page title, move focus to the new main heading or to the main region and announce the change if needed. Without this, a user may press a link and hear nothing, then have to hunt for what changed. Frameworks differ, so test the behavior with a keyboard and a screen reader on every major route.
Quick reference for developers
| Need | Use |
|---|---|
| A clickable action | A button element |
| Navigation to another page | A link element with an href |
| A focus style | The :focus-visible selector with a clear outline |
| A skip link | An anchor to the main landmark, first in the page |
| A dialog | The dialog element or a tested pattern that traps and restores focus |
| Hidden content | The hidden attribute or display none, so it cannot be focused |
In short
Everything on your site should be reachable and usable with the keyboard, in a sensible order, with a visible indicator of where you are. Keep native elements, add a skip link, restore a clear focus outline, manage focus in dialogs and drawers, and test your main journeys with the Tab key. If you do those six things, you have dealt with the most common and most serious keyboard problems.
If you are short of time, test only three things: that you can see where focus is, that you can open and close every menu and popup, and that you can complete checkout. Those three account for most of the keyboard problems that cost a business customers.
Make the test part of your release routine, so a change that breaks the keyboard path is caught the same day and not months later when a customer writes in to complain.
Test it
Press Tab from the top of the page and keep going through the whole flow. You should always see where you are, never get stuck and be able to reach everything a mouse user can. The hand-testing steps show the full routine.
Clir's browser-based checks look at keyboard focus; the methodology explains how the focus indicator check works. Pair it with a quick Tab-through of your own.
Common questions
Is it okay to hide the focus ring because it looks ugly?
Not without replacing it. Style it to match your design, but keep it visible.
What is the difference between :focus and :focus-visible?
:focus applies whenever an element has focus, including after a click. :focus-visible applies when the browser decides the focus indicator should show, typically for keyboard use.
What is a keyboard trap?
A place where focus enters but cannot leave using the keyboard, such as a popup with no way to close it. WCAG 2.1.2 forbids it.
Is it OK to hide the focus outline for mouse users?
The :focus-visible selector shows the outline when keyboard navigation is used and can hide it for mouse clicks. Do not remove it completely.
Do I need a skip link on a small site?
It is still useful if you have a header with several links, and it takes a few minutes to add.
See what a scan finds on your own site
Run a free scan on one page, no signup. For the full picture, the $99 One Page assessment adds a detailed report, a Fix Pack and two rechecks.
Clir runs automated checks against WCAG 2.2 Level A and AA success criteria. How Clir tests.