Nested interactive controls (nested-interactive)

The nested-interactive rule flags a control that contains another focusable control – a link inside a button, a button inside an element with role="button". Assistive technology treats the outer control as a single unit and cannot see what is inside it, so the inner control is announced wrongly or not at all. The fix is to put the controls side by side instead of one inside the other.

What the rule means

Some roles – button, link, checkbox, tab, menuitem, option and others – have "presentational children" in WAI-ARIA: whatever is inside them is flattened into their name. A link inside a button is therefore not a link to a screen reader; its text becomes part of the button's name, and the link itself cannot be reached or activated by browsing. Keyboard users may still tab onto it, and then hear something that makes no sense.

HTML says the same from the other direction: a <button> or an <a> must not contain interactive content. Browsers repair such markup in different ways, which is why the result is unpredictable.

Who is affected

Screen reader users, who hear one control where there are two and cannot reach the inner one. Voice-control users, who say the name of the link they see and activate the button around it. Keyboard users, who meet two Tab stops that do the same thing – or different things with no way to tell which is which.

Why the check fails

  • Clickable cards built as <div role="button"> or <a> with a "More" link or a "Favourite" button inside.
  • Buttons with icon links, for example a "Download" button wrapping an <a href>.
  • Accordion headers with role="button" that contain a help link.
  • Table rows or list items turned into controls while they contain links.
  • Component libraries that let you put anything into a button slot.

How to fix it

Make one element the control and keep other controls next to it, not inside it.

<!-- Before: a favourite button inside a clickable card -->
<div class="product-card" role="button" tabindex="0">
  <h2>Desk lamp</h2>
  <p>€49.00</p>
  <button type="button" aria-label="Add desk lamp to favourites">♡</button>
</div>
<!-- After: the title is the link; the favourite button sits beside it -->
<div class="product-card">
  <h2><a href="/products/desk-lamp/">Desk lamp</a></h2>
  <p>€49.00</p>
  <button type="button" aria-label="Add desk lamp to favourites">♡</button>
</div>

To keep the whole card clickable, stretch the link over the card with a positioned ::after and raise the button above it with position: relative; z-index: 1. The card looks and clicks the same; the markup no longer nests.

How to test it manually

  1. Tab through the component. Do you meet two stops for one visual control, or a stop inside another?
  2. With a screen reader, browse the component with the arrow keys. Can you reach and activate the inner control on its own?
  3. Check the accessibility tree: an outer control whose name contains the inner control's text is the tell-tale sign.
  4. Click every part of the card with the mouse and check each does what it says.

4.1.2 Name, Role, Value, Level A. Related: 2.1.1 Keyboard, because the inner control may be out of reach, and 2.5.3 Label in Name for voice users.

How Reviseberg reports it

Reviseberg runs nested-interactive on every crawled page. The issue list shows the rule with its severity, WCAG 4.1.2, the number of affected elements and pages, and the points a fix gets you back; the detail view shows the outer control's selector and HTML snippet. Card and teaser components repeat on listing pages, so the occurrence count is often high – and one component fix clears them all.

Check your cards and teasers – get a free scan

Frequently asked questions

How do I make a whole card clickable without nesting?

Put a real link on the title and stretch it over the card with a pseudo-element. Other buttons in the card sit above it.

Is a link inside <label> nested interactive content?

No, <label> is not a control in this sense. A link to the terms of service inside a checkbox label is allowed, although a link after the label is easier to use.

Does tabindex="-1" on the inner control fix it?

It hides the problem from keyboard users and keeps it for everybody else. Move the control out instead.

Sources

  1. W3C, Understanding SC 4.1.2 Name, Role, Value – https://www.w3.org/WAI/WCAG22/Understanding/name-role-value
  2. Deque University, axe-core 4.13 rule nested-interactive – https://dequeuniversity.com/rules/axe/4.13/nested-interactive
  3. W3C, WAI-ARIA 1.2: Children Presentational – https://www.w3.org/TR/wai-aria-1.2/#childrenArePresentational
  4. WHATWG, HTML Standard: the button element – https://html.spec.whatwg.org/multipage/form-elements.html#the-button-element

See what a scan finds on your site

One page in about thirty seconds, no email needed. The full report covers up to 100 pages and a keyboard journey.