# ARIA hidden element must not be focusable or contain focusable elements

> Canonical HTML version: https://rocketvalidator.com/accessibility-validation/axe/4.11/aria-hidden-focus
> Attribution: Rocket Validator (https://rocketvalidator.com)
> License: CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/)

The `aria-hidden="true"` attribute tells assistive technologies to ignore an element and all of its descendants. This is useful for hiding purely decorative content — such as icon fonts or redundant visuals — that would clutter the screen reader experience. However, a serious problem arises when focusable elements like links, buttons, form inputs, or elements with `tabindex="0"` exist inside an `aria-hidden="true"` container.

When this happens, keyboard users can still `Tab` to those elements, but screen readers won't announce them. The user lands on what feels like an invisible, unlabeled control. They have no way to know what the element is or what it does. This affects blind users, deafblind users, users with low vision who rely on screen readers, and mobility-impaired users who navigate exclusively by keyboard.

It's also important to understand that `aria-hidden="false"` on a descendant does **not** override `aria-hidden="true"` on an ancestor. Once a parent is hidden from the accessibility tree, all children remain hidden regardless of their own `aria-hidden` value. Any focusable children inside that subtree still create the same problem.

## Related WCAG Success Criteria

This rule primarily relates to **WCAG Success Criterion 4.1.2: Name, Role, Value (Level A)**. This criterion requires that for all user interface components, the name and role can be programmatically determined, and states, properties, and values can be programmatically set. A focusable element inside an `aria-hidden="true"` container violates this because its name and role are stripped from the accessibility API while it remains reachable via keyboard — making it impossible for assistive technologies to convey its purpose. This rule is flagged across WCAG 2.0, 2.1, and 2.2 at Level A, as well as in Trusted Tester, EN 301 549, and RGAA guidelines.

## How to Fix It

There are several strategies to resolve this issue:

1. **Remove `aria-hidden="true"`** from elements that contain focusable children, if those children need to be interactive.
2. **Remove focusable elements** from inside the `aria-hidden="true"` container if the entire section is truly meant to be hidden.
3. **Make focusable elements unfocusable** by adding `tabindex="-1"` to links, buttons, or other interactive elements inside the hidden container.
4. **Use the `disabled` attribute** on form controls (not `aria-disabled`, which does not actually prevent focus).
5. **Hide elements with CSS** using `display: none` or `visibility: hidden`, which removes them from both the accessibility tree and the focus order simultaneously.

If you need to hide content from assistive technologies, ensure equivalent meaning and functionality is still available through other accessible means.

## Examples

### Incorrect: Focusable link inside `aria-hidden="true"`

The link is removed from the accessibility tree but still receives keyboard focus.

```html
<div aria-hidden="true">
  <a href="/home">Home</a>
</div>
```

### Incorrect: Offscreen focusable link inside `aria-hidden="true"`

Moving a link offscreen does not remove it from the focus order.

```html
<div aria-hidden="true">
  <a href="/" style="position:absolute; top:-999em">Link</a>
</div>
```

### Incorrect: Using `aria-disabled` instead of `disabled`

The `aria-disabled` attribute does not actually prevent the input from receiving focus.

```html
<div aria-hidden="true">
  <input aria-disabled="true" />
</div>
```

### Incorrect: Element with `tabindex="0"` and `aria-hidden="true"`

Adding `tabindex="0"` makes a normally non-focusable element focusable, creating a conflict with `aria-hidden="true"`.

```html
<p tabindex="0" aria-hidden="true">Some descriptive text</p>
```

### Incorrect: Trying to override `aria-hidden` on a descendant

Setting `aria-hidden="false"` on a child does not re-expose it when a parent has `aria-hidden="true"`. The button remains hidden from assistive technologies but still receives focus.

```html
<div aria-hidden="true">
  <div aria-hidden="false">
    <button>Submit</button>
  </div>
</div>
```

### Incorrect: Focusable `<summary>` inside `aria-hidden="true"`

The `<summary>` element is natively focusable.

```html
<details aria-hidden="true">
  <summary>More info</summary>
  <p>Additional details here.</p>
</details>
```

### Correct: Non-focusable content inside `aria-hidden="true"`

A paragraph with no interactive elements is safe to hide.

```html
<p aria-hidden="true">Decorative description text</p>
```

### Correct: Focusable elements hidden with CSS `display: none`

Using `display: none` removes the link from both the focus order and the accessibility tree.

```html
<div aria-hidden="true">
  <a href="/" style="display:none">Link</a>
</div>
```

### Correct: Focusable elements made unfocusable with `tabindex="-1"`

Adding `tabindex="-1"` removes the button from the tab order.

```html
<div aria-hidden="true">
  <button tabindex="-1">Close</button>
</div>
```

### Correct: Form input properly disabled with the `disabled` attribute

The `disabled` attribute prevents the input from receiving focus entirely.

```html
<input disabled aria-hidden="true" />
```

### Correct: Removing `aria-hidden` and keeping elements interactive

If the content needs to be focusable, simply don't hide it from assistive technologies.

```html
<div>
  <a href="/home">Home</a>
</div>
```
