2.4.12 Focus Not Obscured (Enhanced)

WCAG 2.2 · 2.4.12 AAA Operable

What it requires

When a user interface component receives keyboard focus, no part of it is hidden by author-created content. This is the enhanced version of 2.4.11: where the Level AA criterion only asks that the focused item is not entirely hidden, this AAA criterion requires that the focused item is fully visible — sticky headers, footers, cookie banners, or floating widgets must not cover any portion of it.

Sighted keyboard users — including people with motor disabilities who cannot use a mouse, and people using switch devices or alternative keyboards — rely on the visible focus indicator to know where they are. If a sticky element partially overlaps the focused control, they lose track of position, may activate the wrong element, or cannot read the label of the item they are about to operate. People with low vision and cognitive disabilities are especially affected.

How to detect it

Checks for 2.4.12
Check How Catches
Keyboard sweep Tab through every focusable item, especially near sticky headers/footers and after opening dialogs or banners. Any item even partly covered when focused.
Sticky overlap Scroll so a fixed/sticky region is on screen, then Tab into content beneath it. Headers/footers clipping the focused row or link.
Zoom & reflow Repeat the sweep at 200%–400% zoom and narrow viewports. Overlaps that only appear when layout compresses.
Automated tools axe, Lighthouse, WAVE. Cannot reliably detect this — it requires manual focus testing.

How to fix it

  1. Identify every persistent overlay: sticky/fixed headers, footers, cookie bars, chat widgets.
  2. Reserve space for them with scroll-padding so scrolled-to focus lands clear of the overlay.
  3. Ensure the focus indicator and the whole component sit above overlays, or are never covered.
  4. Make dismissable banners truly dismissable and out of the focus path once closed.
  5. Re-test the full keyboard sweep at multiple zoom levels.
/* Sticky header 64px tall — keep focused items below it */
:root { --header-h: 64px; }

html {
  scroll-padding-top: var(--header-h);
  scroll-padding-bottom: 3rem; /* clear of a sticky footer */
}

.site-header { position: sticky; top: 0; }

Copy-paste tests

Automated coverage

There is no fully automated axe-core rule for this criterion: whether a focused element is partly obscured depends on live focus, scroll position, and stacking. It needs manual review, using the console check and keyboard steps below.

Run this in the browser console

find-sticky-overlays.js
// Read-only: lists fixed/sticky elements that could cover a focused control.
const suspects = [...document.querySelectorAll('*')].filter(el => {
  const p = getComputedStyle(el).position;
  return (p === 'fixed' || p === 'sticky') && el.offsetHeight > 0;
}).map(el => {
  el.style.outline = '2px solid magenta'; // visual only
  const r = el.getBoundingClientRect();
  return { tag: el.tagName.toLowerCase(), id: el.id, top: Math.round(r.top), height: Math.round(r.height), el };
});
console.table(suspects);
console.log('Now Tab through the page and watch these magenta regions.', suspects);

What to check manually: Tab to every control near each highlighted region and confirm no part of the focused item or its focus ring is covered. No script can confirm the indicator stays fully visible at 200%–400% zoom or after a banner appears.