Tab through your own homepage. On many sites, somewhere around the fifth or sixth press, focus lands on a link sitting directly behind the sticky header. Nothing on screen changes. The page looks stuck, and the person on the keyboard has no idea where they are.
WCAG 2.2 gave this problem a name: Success Criterion 2.4.11, Focus Not Obscured (Minimum). It is Level AA, and the fix is usually a few lines of CSS. The harder part is knowing it exists, because automated scans tend not to flag it.
What the criterion says
When a component receives keyboard focus, it must not be entirely hidden by author-created content: sticky headers and footers, cookie banners, chat launchers and non-modal dialogs.
- At AA, partial overlap is allowed. If a sliver of the focused element is visible, it passes. The stricter AAA criterion, 2.4.12, asks that no part is hidden.
- Content the user opens, such as a menu or tooltip, is treated differently. If they can dismiss it or reveal the focused element without moving focus, it does not count against you.
The W3C lists this exact pattern as a failure (F110) and CSS scroll-padding as a sufficient technique (C43).
Keyboard, switch and voice control users all rely on seeing focus. When it vanishes they keep pressing Tab or assume the page has frozen. People at high zoom have it worst, because a fixed header takes up a bigger share of a smaller viewport.
Where it breaks
- Sticky top navigation. Shift+Tab walks up the page and focus lands under the header.
- Bottom cookie banners. Tabbing down a long form eventually puts focus behind the banner.
- Sticky checkout bars. A pinned "Place order" bar covers the field the user just tabbed into.
- Chat widgets and promotional banners that stay put while the page scrolls.
None of these is wrong on its own. The browser scrolls a focused element only until it is inside the viewport, and it does not know your header covers the top 80 pixels of that viewport.
The CSS fix: scroll-padding
Scroll padding tells the browser how much of the viewport edge to treat as off limits when it scrolls something into view, including a newly focused element:
```css
html {
scroll-padding-top: var(--header-h, 5rem);
scroll-padding-bottom: calc(var(--banner-h, 0px) + 1rem);
}
```
A header is usually a fixed height. Banners change height with width and wrapped text, so measure them:
```js
const banner = document.querySelector('[data-consent-banner]');
if (banner) {
const sync = () =>
document.documentElement.style.setProperty('--banner-h', banner.offsetHeight + 'px');
new ResizeObserver(sync).observe(banner);
sync();
}
```
When the banner is dismissed, hide it with the hidden attribute or display: none, not a transform, so the observer sees zero height and the padding disappears. Add scroll-margin-top to heading anchors so skip links and table-of-contents links do not land under the header.
For cookie banners, you have three workable choices. Make it modal, with a proper dialog that holds focus and makes the page behind it inert (our guide to accessible exit-intent modal popups covers the focus handling). Keep it non-modal and pad for it. Or let it close when focus leaves it. Whichever you pick, it must be reachable and dismissible by keyboard, and the dismissal must be remembered.
How to test it
This takes ten minutes and needs only a keyboard.
- Press Tab slowly from the top of the page and watch each focus ring. Note any press where you lose sight of focus.
- Go backwards with Shift+Tab from the bottom. Sticky headers fail most often in this direction.
- Repeat at a short viewport height and at 200 and 400 percent zoom.
- Test the flows that matter: checkout, sign-up, long forms and any page with a persistent bar.
- Check the page with the banner and chat widget both open and closed.
Automated checkers generally cannot tell whether a focused element is covered at the moment of focus. That is the gap we describe in why a perfect Lighthouse score does not mean your site is accessible. For a starting point on manual checks, see how to conduct accessibility reviews before launch without experts.
Where this sits in your compliance picture
Check which WCAG version your contracts and regulations name. The US Department of Justice rule for state and local government websites, for example, names WCAG 2.1 Level AA, and 2.4.11 is a 2.2 criterion. That is not a reason to skip it: the fix is cheap, it removes a real barrier, and teams that build to 2.2 now avoid reworking components later.
Frequently asked questions
Does it fail if the header covers only part of the focused element? Not at Level AA. 2.4.11 fails when the element is entirely hidden. AAA criterion 2.4.12 asks that no part is hidden.
Is a cookie banner always a failure? No. It passes if it is modal, if the page scrolls clear of it, or if it closes when focus leaves it. It fails when it can fully cover a focused element.
Does scroll-padding work in every browser? Current versions of the major browsers support it, but confirm against your own support matrix and test on real devices.
The short version
List every fixed or sticky element on your site, work out how much viewport each takes, and tell the browser to keep focus clear of it. Then Tab through your most important pages to confirm.
If you want a second pair of eyes on keyboard behaviour across your product, book a call with a Wally accessibility expert.
