About This HTML Issue
The HTML living standard defines both <a> and <button> as interactive content. Interactive content elements cannot be descendants of other interactive content elements. When you place a <button> inside an <a>, you create an ambiguous situation: should a click activate the link navigation or the button action? Browsers handle this inconsistently, which leads to unpredictable behavior for all users.
This is especially problematic for accessibility. Screen readers and other assistive technologies rely on a clear, well-defined element hierarchy to communicate the purpose of controls to users. A button nested inside a link creates a confusing experience — the user may hear both a link and a button announced, with no clear indication of what will actually happen when they activate it. Keyboard navigation can also break, as focus behavior becomes unreliable.
The same rule applies to elements that aren’t literally <button> but carry role="button". For example, a <span role="button"> inside an <a> tag triggers the same validation error, because the ARIA role makes it semantically interactive.
How to Fix It
The fix depends on what you’re trying to achieve:
-
If the element should navigate to a URL, use an
<a>element and style it to look like a button with CSS. Remove the<button>entirely. -
If the element should perform a JavaScript action, use a
<button>element and remove the wrapping<a>. Attach the action via an event listener. - If you need both a link and a button, place them side by side as siblings rather than nesting one inside the other.
Examples
❌ Invalid: Button inside a link
<a href="/dashboard">
<button>Go to Dashboard</button>
</a>
✅ Fixed: Link styled as a button
If the goal is navigation, use a link and style it with CSS:
<a href="/dashboard" class="btn">Go to Dashboard</a>
.btn {
display: inline-block;
padding: 8px 16px;
background-color: #007bff;
color: #fff;
text-decoration: none;
border-radius: 4px;
}
✅ Fixed: Button with a JavaScript action
If the goal is to trigger an action (like navigating programmatically), use a button on its own:
<button type="button" onclick="window.location.href='/dashboard'">
Go to Dashboard
</button>
❌ Invalid: Element with role="button" inside a link
<a href="/settings">
<span role="button">Settings</span>
</a>
✅ Fixed: Remove the redundant role
Since the <a> element already communicates interactivity, the inner role="button" is unnecessary and conflicting. Simply use the link directly:
<a href="/settings">Settings</a>
❌ Invalid: Link inside a button
Note that the reverse — an <a> inside a <button> — is also invalid for the same reason:
<button>
<a href="/home">Home</a>
</button>
✅ Fixed: Choose one element
<a href="/home" class="btn">Home</a>
The key principle is simple: never nest one interactive element inside another. Pick the element that best matches the semantics of your use case — <a> for navigation, <button> for actions — and use CSS to achieve the visual design you need.
Find issues like this automatically
Rocket Validator scans thousands of pages in seconds, detecting HTML issues across your entire site.