# Elements with a role that makes children presentational must not contain focusable content.

> Canonical HTML version: https://rocketvalidator.com/accessibility-validation/accesslint/0.16/aria/presentational-children-focusable
> Attribution: Rocket Validator (https://rocketvalidator.com)
> License: CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/)

Certain ARIA roles treat all of their child elements as presentational. This means the browser strips those children from the accessibility tree, making them invisible to assistive technologies like screen readers. The affected roles are: `button`, `checkbox`, `img`, `meter`, `menuitemcheckbox`, `menuitemradio`, `option`, `progressbar`, `radio`, `scrollbar`, `separator`, `slider`, `switch`, and `tab`.

When a focusable element (such as a link, input, or anything with a `tabindex`) is nested inside one of these roles, keyboard users can tab to it, but screen reader users cannot perceive it. The focusable element has no node in the accessibility tree, so it lacks a programmatic name and role. A screen reader may announce nothing at all, or something confusing, when focus lands on it. This creates a disconnect between what keyboard users experience and what screen reader users experience.

This issue relates to WCAG 2.0 success criterion **4.1.2 Name, Role, Value** (Level A), which requires that all user interface components expose their name, role, and state to assistive technologies. A focusable element hidden by presentational children semantics fails this requirement because it is reachable by keyboard but has no accessible information.

Browser support for presentational children is inconsistent. Some browsers ignore the spec and keep child elements in the accessibility tree even when the parent role should make them presentational. This means a page might work in one browser but fail in another. Writing correct markup avoids this ambiguity entirely.

## How to fix it

The fix depends on the specific situation:

1. Move the focusable element outside the parent that has the presentational children role. Use `aria-labelledby` or other techniques to maintain the visual and semantic relationship if needed.
2. Remove focusability from the child element. If the child does not need to be independently focusable (for example, a decorative input inside a custom checkbox), add the `disabled` attribute or remove `tabindex`.
3. Restructure the component so that interactive content is not nested inside a role with presentational children.

## Examples

### Incorrect: link inside a button

The `<a>` element inside the `<button>` is focusable, but the `button` role makes its children presentational. Keyboard users can tab to the link, but screen readers cannot identify it.

```html
<button>
  Save to <a href="/cloud">cloud</a>
</button>
```

### Correct: link moved outside the button

The link is placed adjacent to the button so both elements are in the accessibility tree and reachable by all users.

```html
<button>Save</button>
<a href="/cloud">Cloud options</a>
```

### Incorrect: focusable span inside a role with presentational children

The `<span>` with `tabindex="0"` inside the `tab` role is keyboard focusable but invisible to assistive technologies.

```html
<div role="tablist">
  <div role="tab" aria-selected="true">
    <span tabindex="0">Settings</span>
  </div>
</div>
```

### Correct: tabindex moved to the tab element itself

The `tab` element is the focusable element, and its text content provides the accessible name. No children need independent focusability.

```html
<div role="tablist">
  <div role="tab" tabindex="0" aria-selected="true">
    Settings
  </div>
</div>
```

### Incorrect: checkbox role wrapping a link

The link inside the `checkbox` role is stripped from the accessibility tree but remains in the tab order.

```html
<span role="checkbox" aria-checked="false" tabindex="0">
  I agree to the <a href="/terms">terms of service</a>
</span>
```

### Correct: link placed outside the checkbox

The link is moved outside the `checkbox` role. `aria-labelledby` connects the checkbox to its full label text.

```html
<p id="terms">
  <span role="checkbox" aria-checked="false" tabindex="0" aria-labelledby="terms">
    I agree to the
  </span>
  <a href="/terms">terms of service</a>
</p>
```

### Correct: disabled input inside a menuitemcheckbox

The `<input>` is disabled, so it is not part of sequential focus navigation. The `role="none"` attribute ensures browsers that do not support presentational children also ignore it.

```html
<ul role="menu">
  <li role="menuitemcheckbox" aria-checked="true">
    <input type="checkbox" role="none" disabled checked />
    Sort by date
  </li>
</ul>
```
