aria-hidden-focus
ARIA hidden elements must not be focusable
Checks that aria-hidden="true" elements are not focusable and do not contain focusable descendants.
Applies to. Applies to elements that have aria-hidden="true", the value read in any case and with surrounding whitespace ignored (aria-hidden="TRUE" hides content in browsers too).
Expectation. No element with aria-hidden="true" may itself be focusable, and no focusable element may exist within an aria-hidden="true" subtree.
What a finding reports.
metrics.focusableTotal: how many focusable elements the hidden element holds, counting itself if it is focusable.metrics.focusableDescendants: how many of those are inside it.metrics.rootIsFocusable: whether the hidden element itself can take focus.offenders: up to 5 of the focusable elements. Each item gives itstag, itstabindex, itshref(a link), itstype(an input) and itsvisibilityHints.metrics.offendersCapturedis how many are listed.metrics.visibilityHints: ways the focusable elements are made invisible while still taking focus:opacityZero,offscreen,clipped,zeroSizeOverflowHidden. Such an element is a focus stop a sighted keyboard user cannot see.metrics.modalOpen: whether a modal dialog was open elsewhere on the page, which turns the finding into one to review.runtimeProbe:nullunless focusing the one focusable element moved focus straight out of the hidden element. Then it holdsredirected: true, the tag and id of the element focus moved to (redirectedToTag,redirectedToId) andfocusTrace, the elements focus passed through. A hidden focus sentinel that hands focus on like this is reported for review.
These data.details fields help to read and reproduce a finding. Apart from reasonCode and the few fields Output schema names as stable, they are not a stable contract: a field may be renamed or dropped in a minor release, so don’t build on them.
Examples
<div aria-hidden="true"><p>Decorative text</p></div>
Nothing inside the hidden subtree is focusable, so hiding it from assistive tech leaves no dead focus stop.
<div aria-hidden="true"><a href="/x">Link</a></div>
The link stays in the tab order even though aria-hidden removes it from the accessibility tree.
How to check
When this rule can’t decide, it reports cantTell and leaves the question to a person. Each question it can ask is listed here under its reason code, with the steps to answer it. A finding carries the same steps as howToCheck, in the scan’s language. See Output schema.
ariaHiddenFocusable_modalOpen_needsReview
- Find the element the report names, behind the modal dialog open on the page, and note what in it can take focus.
- With the dialog open, press Tab repeatedly, then Shift+Tab, and watch where focus goes.
- Whenever focus seems to leave the dialog, check document.activeElement in the developer tools console.
Pass. Focus stays inside the open dialog and never reaches the hidden content behind it.
Fail. Focus reaches content behind the dialog inside aria-hidden="true", where a screen reader announces nothing, which fails WCAG 4.1.2.
ariaHiddenFocusable_runtimeRedirect_needsReview
- Click just before the element the report names, then press Tab until focus should reach it.
- Watch where focus lands and check document.activeElement in the developer tools console.
- Press Shift+Tab from the control after it and see whether focus stops on the hidden element or passes straight on.
Pass. Focus never stays on the hidden element: it passes straight on to a visible control, as a focus trap's sentinel does.
Fail. Focus can stay on the element inside aria-hidden="true", where a screen reader announces nothing, which fails WCAG 4.1.2.