HTML Guides for interactive content
Learn how to identify and fix common HTML validation errors flagged by the W3C Validator — so your pages are standards-compliant and render correctly across every browser. Also check our Accessibility Guides.
An <a> element with an href attribute is interactive content, and interactive content cannot appear inside another <a> element.
The href attribute is what triggers this error. A link that points somewhere is interactive, and the HTML specification does not allow one interactive element to contain another. The outer <a> is already interactive, so a second linked <a> nested anywhere inside it, even several elements deep, makes the markup invalid. An <a> without href is just a placeholder and is allowed inside a link, which is why the validator names the attribute explicitly.
When you write one <a href> directly inside another, the HTML parser closes the outer link as soon as it reads the inner <a> tag, and the validator reports Start tag “a” seen but an element of the same type was already open instead. The error on this page appears only when the nesting survives parsing, for example when a link wraps a whole table that has links in its cells. The page then has a real link inside a link: browsers can't tell which destination a click should follow, and screen readers may announce the wrong link or skip one.
The fix is to give each link its own space so that no <a href> sits inside another <a href>.
Invalid example
<a href="/products/42">
<table>
<tr>
<td>Trail running shoes</td>
<td><a href="/reviews/42">Read reviews</a></td>
</tr>
</table>
</a>
Valid example
<table>
<tr>
<td><a href="/products/42">Trail running shoes</a></td>
<td><a href="/reviews/42">Read reviews</a></td>
</tr>
</table>
An <img> with a usemap attribute is interactive content, so it can't be placed inside an <a> element.
The usemap attribute connects the image to a <map>, whose <area> elements define clickable regions, each usually with its own href. That makes the image interactive, and the HTML specification doesn't allow interactive content anywhere inside an <a>, whether or not the link has an href. A plain <img> without usemap is fine inside a link, which is why the validator names the attribute.
Wrapping an image map in a link puts links inside a link. A click on a region could follow the region's href or the outer link's, depending on the browser, and screen readers may announce the regions as links nested inside another link.
Decide which behavior the image needs. If the regions matter, move the image out of the <a>, and add a separate link next to it if you still want one to the whole destination. If the image only needs to be a single link, remove the usemap attribute and the unused <map>.
Invalid example
<a href="/regions">
<img src="regions.png" alt="Regions" usemap="#regions" width="200" height="300">
</a>
<map name="regions">
<area shape="rect" coords="0,0,200,150" href="/north" alt="North region">
<area shape="rect" coords="0,150,200,300" href="/south" alt="South region">
</map>
Valid example
<img src="regions.png" alt="Regions" usemap="#regions" width="200" height="300">
<map name="regions">
<area shape="rect" coords="0,0,200,150" href="/north" alt="North region">
<area shape="rect" coords="0,150,200,300" href="/south" alt="South region">
</map>
<p><a href="/regions">View all regions</a></p>
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>
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.
1K Weekly
1,000 monthly checks. Cancel anytime.
Get 1K Weekly →Join teams across 40+ countries