( Operable / WCAG 2.4.11 )

Focused element is hidden behind a sticky header or footer

SeriousLevel AAWCAG 2.4.11 — Focus Not Obscured (Minimum)

What is this issue?

A sticky or fixed-position element (most often a header pinned to the top of the viewport while the page scrolls beneath it) sits on top of content in the normal document flow. When keyboard focus moves to an element that happens to scroll into the region the sticky element occupies, the sticky element visually covers it completely, hiding a focus indicator that’s perfectly present and correctly styled in the underlying CSS.

This is a placement problem, not a styling problem: nothing about the focus indicator itself is wrong. The element it belongs to is simply positioned, at the moment of scrolling, directly underneath something else layered on top of it. The user has no way to tell where focus is until they Tab past the obscured region entirely.

Why does this matter?

Sticky headers have become close to a default pattern across modern web design, which means this specific failure has become correspondingly common: any page with a pinned header and no scroll-offset configuration is affected the instant a keyboard user tabs to any element that would otherwise scroll to the very top of the viewport.

The user experience this produces is functionally identical to having no focus indicator at all, even though the underlying CSS is completely correct: from the user’s point of view, focus simply vanishes for one or more Tab presses, then reappears once they’ve tabbed past the sticky region. That gap is disorienting in exactly the same way a genuinely missing indicator is, which is why RedFlag treats it as a distinct, equally serious check rather than folding it into the basic visibility rule.

Who is affected?

  • Low vision users: already relying on a focus indicator’s visibility to track position, lose that tracking entirely for however long the sticky element covers it, with no way to tell whether focus moved somewhere unexpected or is simply hidden.
  • Keyboard users: experience focus seeming to disappear for one or more Tab presses each time it passes behind the sticky region, breaking the continuous visual thread they rely on to navigate confidently.
  • Motor impairments: users navigating via switch device or head pointer face the same visibility gap, with the added cost that re-locating a lost focus position often requires additional deliberate input their input method makes more effortful than a quick mouse glance.

What users experience

Marcus has low vision and uses keyboard navigation with a 200% browser zoom to read comfortably. On a documentation site with a sticky top navigation bar roughly 80 pixels tall, he tabs through a long article’s table of contents links. Each time focus moves to a heading link near the top of a scrolled section, the browser scrolls it to the very top of the viewport, directly behind the sticky navigation bar. He sees the page scroll, sees no focus ring anywhere, and has no way to tell whether his last Tab press actually landed on the link he intended or somewhere else entirely, so he has to Tab once more and watch carefully to infer where he actually is.

How do I fix it?

Add scroll-padding-top to the <html> element, set to at least the sticky header’s rendered height. This works because scroll-padding-top tells the browser to reserve that much space at the top of the viewport when scrolling any element into view (including the browser’s own built-in scroll-into-view behavior that runs automatically when focus moves), so a focused element now stops just below the sticky header instead of directly underneath it.

If your sticky element’s height changes at different breakpoints or in different states (a header that shrinks on scroll, for example), set scroll-padding-top dynamically via JavaScript to match the sticky element’s actual current height, rather than hardcoding a single value that only holds true in one state. For sticky footers, the equivalent scroll-padding-bottom property solves the identical problem for elements near the bottom of the viewport.

Code Examples

Before
header {
  position: sticky;
  top: 0;
  height: 64px;
}
/* Focused elements scrolled to the top land behind the header */
After
header {
  position: sticky;
  top: 0;
  height: 64px;
}

html {
  scroll-padding-top: 80px; /* header height plus a small buffer */
}

scroll-padding-top changes nothing about the header’s own styling; it only tells the browser to leave that much space clear at the top of the viewport whenever something scrolls into view, focused elements included. The sticky header keeps working exactly as designed, while every focused element underneath it now lands visibly below it instead of hidden beneath it.

Common Mistakes

Mistake: “Our focus indicator has great contrast and a thick outline, so this can’t be a focus-visibility problem.” A well-designed indicator is exactly what this rule assumes going in; the defect has nothing to do with the indicator’s own styling and everything to do with a separate element physically covering it. The best-designed focus ring in the world is invisible if something else is rendered on top of it.

Mistake: “This is a rare edge case that only affects one or two elements near the top of each page.” Any element that, at the moment it receives focus, would scroll to a screen position the sticky element occupies is affected, which in practice can be a large share of a page’s headings, links, and form fields, not just the very first element on the page.

Mistake: “We already use scroll-margin-top on individual elements, so this is covered.” scroll-margin-top set on individual elements works, but has to be applied consistently to every element that could scroll into the obscured region; miss one, and it’s unprotected. scroll-padding-top on the <html> element covers every scroll-into-view case on the page from a single declaration, which is both simpler and harder to accidentally miss.

How RedFlag Detects This

Custom automated: RedFlag’s own DOM detector, runs on every scan. RedFlag computes the rendered style for every element on the page, collects any using position: sticky or position: fixed (up to three reported per scan), and flags them specifically when the <html> element’s computed scroll-padding-top value is exactly 0, the condition under which a sticky element is most likely to obscure a scrolled-to focus target.

False negative: this is a page-level heuristic, not a true per-element occlusion measurement; it does not verify that a sticky element actually overlaps any specific focused control, so a page with correctly configured scroll-padding-top but a still-overlapping edge case elsewhere won’t be caught, and the reverse is also possible if a non-zero scroll-padding-top happens to be insufficient for the sticky element’s actual height. False positive: a sticky or fixed element that never actually overlaps any focusable content (a decorative sticky background element, for instance) can still be flagged purely for having scroll-padding-top: 0, regardless of whether real overlap ever occurs. Manual step: Tab through the page and specifically watch what happens as focus passes behind any sticky or fixed element, confirming the indicator stays visible or clears the obscured region promptly.

Manual Testing

  1. Open the page in Chrome or Firefox using only the keyboard.
  2. Identify every sticky or fixed-position element: headers, footers, cookie banners, chat widgets.
  3. Tab through the page, paying particular attention to elements near the top or bottom of the viewport, or anywhere a heading anchor link might scroll to.
  4. At each Tab press, confirm the focus indicator remains at least partially visible and not fully hidden behind a sticky element.
  5. If a focused element disappears entirely behind a sticky element for even one Tab press, the check fails.

2.4.11 Focus Not Obscured (Minimum): When an element receives keyboard focus, it must not be entirely hidden by author-created content, such as sticky headers or footers. This rule is a direct, common cause of that failure: a sticky element with no scroll-offset configuration frequently covers a focused element completely, which is exactly what this Level AA criterion (new in WCAG 2.2) prohibits.

Focused element has no visible focus indicator is this trio’s foundational check under 2.4.7 Focus Visible; it assumes an indicator can be seen at all, which this rule’s failure mode specifically undermines through occlusion rather than missing styling.

Focus indicator does not meet minimum size or contrast is the third page in the trio, covering 2.4.13 Focus Appearance: how good the indicator looks once it’s confirmed to exist and be visible, rather than whether something else is covering it.

Focusable element is inside an aria-hidden container covers a related but distinct focus-management defect, where hidden content remains reachable rather than visible content becoming obscured.

References

Frequently asked questions

Is this the same rule as Focused element has no visible focus indicator?

No, they cover different WCAG 2.2 criteria and different failure mechanisms. Focused element has no visible focus indicator (2.4.7) is about whether a focus indicator exists at all in the CSS. This rule (2.4.11) assumes an indicator exists and is styled correctly, but gets visually covered by a sticky element on screen, so it is invisible in practice even though it is technically rendered.

Is Focus Not Obscured the same as Focus Not Obscured (Enhanced)?

No. This rule documents 2.4.11 Focus Not Obscured (Minimum), a Level AA criterion requiring that at least part of the focused element remains visible. Its stricter sibling, 2.4.12 Focus Not Obscured (Enhanced), is Level AAA and requires the entire focused element to remain visible with no exceptions, a higher bar most sites do not target.

Does this only apply to sticky headers, or footers and cookie banners too?

Any position: sticky or position: fixed element can cause this: sticky headers are the most common, but sticky footers, persistent cookie-consent banners, and fixed chat widgets all create the identical overlap risk if scroll offsetting is not configured to account for them.

Why doesn't the browser handle this automatically when focus moves?

Browsers do scroll a focused element into view automatically, but that built-in behavior has no awareness of a sticky element layered on top of the page: it scrolls the element to the edge of the viewport, which can still land it directly underneath a sticky header unless scroll-padding-top explicitly reserves that space.