How to fix: Focusable elements hidden with aria-hidden
Fix focusable elements inside aria-hidden="true" by removing the aria-hidden, or by making the hidden content genuinely unreachable (the inert attribute, tabindex="-1", or disabled), because aria-hidden removes content from screen readers but not from the keyboard — focus lands on a ghost the user can't hear.
What it is
aria-hidden="true" removes an element and its entire subtree from the accessibility tree, so screen readers act as if it doesn't exist. What it does NOT do is remove anything from the keyboard tab order. A link, button, or form field inside an aria-hidden region is still perfectly focusable — pressing Tab moves focus onto it as usual — but assistive technology has nothing to announce when it gets there.
The result is what practitioners call ghost focus: a screen reader user presses Tab, focus visibly moves (or moves invisibly, if the region is also styled off-screen), and the screen reader falls silent. The user has no idea where they are, what the control does, or how many more silent stops lie ahead. It is one of the most disorienting keyboard experiences a page can produce.
The classic sources are components that hide visually-inactive content with aria-hidden while leaving it in the DOM: closed modals and drawers, off-screen carousel slides, collapsed mega-menus, and duplicated mobile/desktop navigation. The subtree is hidden from screen readers, but every link and button inside it still sits in the tab order.
Who it affects & why it matters
Screen reader users who navigate by keyboard are affected most directly: each focusable element inside an aria-hidden region is a silent tab stop that breaks their mental model of the page. A hidden carousel with nine slides of linked cards can add dozens of mute stops between two visible controls.
Sighted keyboard users suffer a related symptom when the hidden content is positioned off-screen rather than display:none — focus disappears from view while they tab, then reappears somewhere else entirely. Switch-device users, for whom every extra stop costs real effort, pay the highest price for a tab order padded with unreachable ghosts.
A focusable element whose name, role, and state are stripped from assistive technology fails WCAG 2.1 Success Criterion 4.1.2 Name, Role, Value — Level A, the minimum tier — and Level AA, which courts treat as the ADA benchmark, includes it. The failure is mechanical to demonstrate: turn on a screen reader, press Tab, and record the silence.
It is also extremely common, because it hides inside popular carousel, modal, and menu implementations rather than hand-written code — which means it reaches production on otherwise careful sites. The modern fix is one attribute: inert removes a subtree from both the tab order and the accessibility tree, finally making "hidden" mean hidden everywhere.
How to fix it
- Find every element with aria-hidden="true" and list the focusable content inside it: links with href, buttons, inputs, selects, textareas, and anything with a tabindex.
- Decide the intent. If the content is supposed to be hidden (closed modal, inactive slide), it must leave the keyboard too — add the inert attribute to the same wrapper, or hide it with display:none / the hidden attribute.
- If the content is actually visible and interactive, the aria-hidden is the bug — remove it so screen readers can announce what keyboard users can reach.
- When you toggle visibility with JavaScript, toggle reachability in the same place: open ⇒ remove aria-hidden and inert; closed ⇒ set both.
- Verify by pressing Tab through the page with a screen reader running — every focus stop should announce something — then re-scan.
<div class="modal" aria-hidden="true">
<button class="close" aria-label="Close">×</button>
<a href="/checkout">Continue to checkout</a>
</div><!-- inert removes the subtree from BOTH the tab order and
the accessibility tree, so hidden truly means hidden -->
<div class="modal" aria-hidden="true" inert>
<button class="close" aria-label="Close">×</button>
<a href="/checkout">Continue to checkout</a>
</div>How AccessKnight detects this
AccessKnight selects every element carrying aria-hidden="true" and searches it for keyboard-focusable content: links with an href, buttons, form fields, contenteditable regions, and anything with a tabindex — skipping controls that are disabled or set to tabindex="-1". Subtrees that are statically inert (the hidden or inert attribute, or inline display:none / visibility:hidden styles) are not flagged, because the keyboard can't reach those either. Content hidden only by an external stylesheet class can't be confirmed statically, so pair the scan with a quick Tab-through to check any remaining findings.