Back to reviews and guides

WCAG 2.4.12 Focus Not Obscured (Enhanced): Preventing Focus from Being Hidden

WCAG 2.4.12 Focus Not Obscured requires that when focus moves to an element the element and its focus indicator are not hidden by other content, clipping, or scrolling. This article explains what obscures focus, gives developer techniques, a testing checklist, common mistakes, and practical code patterns to keep focus visible.

WCAG 2.4.12 Focus Not Obscured (Enhanced): what this success criterion requires

WCAG 2.4.12 Focus Not Obscured requires that when keyboard focus moves to an element its focus indicator and the element are not hidden by other content. That means users who rely on keyboard navigation must always be able to see where focus is, even if overlays, fixed headers, or transforms are present.

Why this matters

People who use the keyboard, switch devices, or rely on visible focus cues need a clear, unobstructed target. If a focus ring is covered or pushed off-screen, users can lose context and become unable to continue interacting with the page. This success criterion reduces that risk by making visible focus reliable.

WCAG already includes criteria about focus visibility. Focus Not Obscured adds a requirement about obstruction and visibility in layout and scrolling. It is not only about the style of the focus indicator. It also covers whether the focused element or its visible focus indicator is hidden by other content or clipped by overflow or transforms.

When focus is considered obscured

  • The focus outline is covered by a fixed header, overlay, or other element.
  • The focused element is off-screen because of scrolling or clipping and the browser or script does not bring it into view.
  • CSS transforms, overflow hidden, or overflow: auto clip the visible focus indicator so the user cannot see it.

Developer techniques that satisfy WCAG 2.4.12

Use the following reliable techniques when implementing focus management.

1. Ensure the browser scrolls focused elements into view

Let the browser handle focus scrolling when possible. If you use JavaScript to move focus, call element.focus() and then ensure the element is visible. If the element may be hidden by a fixed header, adjust the scroll so it is fully visible.

2. Avoid covering focus with overlays

When showing overlays, either move focus into the overlay and ensure the previously focused element remains visible if shown, or ensure the overlay does not cover the focus target when focus is intentionally left outside. Use stacking order and aria-hidden appropriately.

3. Prevent clipping by transforms and overflow

Do not rely on CSS transforms that create new stacking contexts in ways that clip focus outlines. Avoid overflow: hidden on containers that might clip the focused element. If clipping is necessary, provide a visual alternative that remains visible.

4. Make visible focus styles robust

Use a focus style that contrasts with the background and is thick enough to remain visible when zoomed. Example CSS to supplement default focus is outline: 3px solid #005a9c; outline-offset: 2px;. Always keep a non-color cue such as a double border or an outline so color blindness or forced colors do not remove the cue.

5. Adjust for fixed headers and in-page anchors

When an in-page link moves focus to a target under a fixed header, offset the scroll by the header height so the target and its focus indicator are visible. Use CSS scroll-padding-top on the root or call a small scroll adjustment after focusing.

Practical step-by-step: make focus visible for a dynamic modal

  1. When opening the modal, add it to the DOM and set role=“dialog” and aria-modal=“true”.
  2. Move focus to the first interactive control inside the modal with element.focus().
  3. Ensure the focused control is not covered by other fixed UI. If it is, reposition the modal or adjust z-index so the control and its focus outline are on top.
  4. Trap focus inside the modal while open. When closing, return focus to a logical element outside the modal and ensure that element is visible.

Testing checklist (manual and assisted)

Test What to look for
Tab through page Every focused element and its focus indicator are fully visible and not covered.
Open overlays and dialogs Focus moves where expected and is not hidden by headers, banners, or other layers.
Increase zoom (browser zoom 200%) Focus indicators still fit on screen and are not clipped.
Use a screen magnifier Magnifier view shows the focused element and its indicator; overlays do not hide it.
Mobile keyboard open Virtual keyboard does not hide the focused field or its indicator; page scrolls so field is visible.

Common mistakes that cause focus to be obscured

  • Using transform: translate() on a container that clips child outlines.
  • Placing focusable elements under a fixed header without scroll padding.
  • Adding overlays with higher z-index that cover the focused element while leaving focus outside the overlay.
  • Removing default focus styles without replacing them with an accessible alternative.
  • Relying on automated tests only. Visual checks are needed for clipped or covered focus indicators.

Edge cases and how to handle them

Focus in complex widgets

For widgets with internal focusable parts, ensure the element that receives tab focus shows a clear external indicator. If internal focus changes, provide an internal visual cue that remains visible even when the widget is inside a scrollable container.

When moving focus is not appropriate

Sometimes scripts must not move focus, for example for live regions that announce changes. In those cases, make sure the changed element is still visible and that any newly interactive control receives a visible cue when it becomes focusable.

Mobile and viewport changes

On mobile, the virtual keyboard can reduce viewport height enough to hide focused inputs. Detect this and scroll the focused control into view so the focus indicator remains visible above the keyboard.

How to prioritise fixes

Start with primary navigation, forms, and modal dialogs. These are the most critical for task completion. Next, check custom widgets and any area with fixed headers or overlays. Finally, audit pages under zoom and with assistive technologies active.

Useful developer tests and small code patterns

  • Use scrollIntoView({ block: ‘nearest’ }) or scrollIntoView({ block: ‘center’ }) after focusing when the browser does not reveal the element correctly.
  • Set html { scroll-padding-top: /* header height */ } for pages with a fixed header so in-page navigation keeps targets visible.
  • Provide a visible focus fallback for forced-colors modes by using @media (forced-colors: active) to ensure the indicator remains visible.

When automated tools will miss problems

Automated checks can confirm the presence of a focusable attribute or a focus style. They cannot reliably determine if another element covers the focused element at runtime, or if clipping occurs under zoom. Add keyboard walkthroughs and manual visual inspection to your test plan.

Summary of practical rules

  • Never leave a focused element covered by any other visible content.
  • Keep focus indicators robust and visible under zoom, magnification, and forced-colors modes.
  • Bring focused elements into view when focus changes, and offset for fixed headers.
  • Test with real devices, keyboard only, and a screen magnifier where possible.

Further reading

Consult the official WCAG documentation for the precise wording of WCAG 2.4.12 and for the normative techniques and failures. Also review guidance on focus management, WAI-ARIA modal dialog patterns, and CSS techniques for visible focus.