Skip to main content
HTML Validation

The element “X” should not appear as a descendant of an element with the attribute “role=Y”.

About This HTML Issue

An interactive element, like a link, a button or a form field, is nested inside an element whose ARIA role doesn't allow interactive descendants, such as role="tab", role="checkbox" or role="option".

ARIA in HTML gives an element with one of these roles the same content rules as the native control it imitates. A <button> can hold text, but no links, buttons or form fields. An element with role="tab", role="checkbox", role="radio", role="option" or role="menuitem" follows the same rule: phrasing content only, with no interactive content and no elements with a tabindex attribute inside it.

Most of these roles also have presentational children in WAI-ARIA, which means browsers shouldn't expose the element's descendants to assistive technologies. A screen reader can announce the tab and read the link inside it as plain text, with no way to reach it as a link. Keyboard users can also end up with two tab stops for what looks like one control.

The validator checks descendants of elements with role set to button, checkbox, img, link, math, menuitem, menuitemcheckbox, menuitemradio, option, progressbar, radio, separator, slider, switch or tab. It flags <a>, <button>, <details>, <dialog>, <embed>, <iframe>, <label>, <select>, <textarea> and every <input> except type="hidden", plus <audio> and <video> with controls and <img> or <object> with usemap. An <a> is flagged even without href, and one with href gets a second warning, "The element "a" with the attribute "href" should not appear...". Both go away with the same fix.

The validator reports this as a warning because the ARIA in HTML section behind it is non-normative. Older validator builds reported it as an error, with "must not appear" in place of "should not appear".

Keep one interactive element per control. Either put the role on the interactive element itself, as in <button role="tab">, or drop the role and use the native element, like an <input type="checkbox"> with its <label>. If the nested element is a separate action, move it out of the element with the role.

Accordions are a common source of role="tab" warnings. Older Bootstrap accordion examples put role="tab" on each panel heading, with a link inside it that opens the panel. An accordion is not a set of tabs, so remove role="tablist", role="tab" and role="tabpanel", and put a <button> with aria-expanded and aria-controls inside each heading.

Invalid example

<div role="tablist" aria-label="Billing">
<div role="tab" id="tab-monthly" aria-selected="true" aria-controls="panel-monthly">
<a href="#panel-monthly">Monthly</a>
</div>
</div>
<div role="tabpanel" id="panel-monthly" aria-labelledby="tab-monthly">
<p>Billed every month.</p>
</div>

Valid example

<div role="tablist" aria-label="Billing">
<button type="button" role="tab" id="tab-monthly" aria-selected="true" aria-controls="panel-monthly">Monthly</button>
</div>
<div role="tabpanel" id="panel-monthly" aria-labelledby="tab-monthly">
<p>Billed every month.</p>
</div>

Valid example for an accordion

<h2>
<button type="button" aria-expanded="false" aria-controls="answer-shipping">How long does shipping take?</button>
</h2>
<div id="answer-shipping" hidden>
<p>Orders ship within two business days.</p>
</div>

Invalid example with a custom checkbox

<div role="checkbox" aria-checked="false" tabindex="0">
<input type="checkbox" id="newsletter">
<label for="newsletter">Email me the newsletter</label>
</div>

Valid example with a native checkbox

<input type="checkbox" id="newsletter">
<label for="newsletter">Email me the newsletter</label>

Find issues like this automatically

Rocket Validator scans thousands of pages in seconds, detecting HTML issues across your entire site.

Help us improve our guides

Was this guide helpful?
🌍 Trusted by teams worldwide

Validate at scale.
Ship accessible websites, faster.

Automated HTML & accessibility validation for large sites. Check thousands of pages against WCAG guidelines and W3C standards in minutes, not days.

Scheduled Reports
API Access
Open Source Standards
€5 / week

1K Weekly

1,000 monthly checks. Cancel anytime.

Get 1K Weekly →

Join teams across 40+ countries