Sobre este problema HTML
O padrão HTML living standard define tanto <a> como <button> como conteúdo interativo. Elementos de conteúdo interativo não podem ser descendentes de outros elementos de conteúdo interativo. Quando você coloca um <button> dentro de um <a>, cria uma situação ambígua: um clique deve ativar a navegação do link ou a ação do botão? Os browsers lidam com isto de forma inconsistente, o que leva a comportamento imprevisível para todos os utilizadores.
Isto é especialmente problemático para acessibilidade. Leitores de ecrã e outras tecnologias assistivas dependem de uma hierarquia de elementos clara e bem definida para comunicar o propósito dos controlos aos utilizadores. Um botão aninhado dentro de um link cria uma experiência confusa — o utilizador pode ouvir tanto um link como um botão anunciados, sem uma indicação clara do que realmente acontecerá quando o ativarem. A navegação por teclado também pode falhar, já que o comportamento do foco se torna não confiável.
A mesma regra aplica-se a elementos que não são literalmente <button> mas têm role="button". Por exemplo, um <span role="button"> dentro de uma tag <a> desencadeia o mesmo erro de validação, porque o role ARIA torna-o semanticamente interativo.
Como corrigir
A correção depende do que você está a tentar alcançar:
-
Se o elemento deve navegar para um URL, use um elemento
<a>e estilize-o para parecer um botão com CSS. Remova completamente o<button>. -
Se o elemento deve executar uma ação JavaScript, use um elemento
<button>e remova o<a>envolvente. Anexe a ação através de um event listener. - Se precisar tanto de um link como de um botão, coloque-os lado a lado como elementos irmãos em vez de aninhar um dentro do outro.
Exemplos
❌ Inválido: Botão dentro de um link
<a href="/dashboard">
<button>Ir para o Dashboard</button>
</a>
✅ Corrigido: Link estilizado como botão
Se o objetivo é navegação, use um link e estilize-o com CSS:
<a href="/dashboard" class="btn">Ir para o Dashboard</a>
.btn {
display: inline-block;
padding: 8px 16px;
background-color: #007bff;
color: #fff;
text-decoration: none;
border-radius: 4px;
}
✅ Corrigido: Botão com uma ação JavaScript
Se o objetivo é desencadear uma ação (como navegar programaticamente), use apenas um botão:
<button type="button" onclick="window.location.href='/dashboard'">
Ir para o Dashboard
</button>
❌ Inválido: Elemento com role="button" dentro de um link
<a href="/settings">
<span role="button">Definições</span>
</a>
✅ Corrigido: Remover o role redundante
Como o elemento <a> já comunica interatividade, o role="button" interno é desnecessário e conflituoso. Simplesmente use o link diretamente:
<a href="/settings">Definições</a>
❌ Inválido: Link dentro de um botão
Note que o reverso — um <a> dentro de um <button> — também é inválido pela mesma razão:
<button>
<a href="/home">Início</a>
</button>
✅ Corrigido: Escolher um elemento
<a href="/home" class="btn">Início</a>
O princípio chave é simples: nunca aninhe um elemento interativo dentro de outro. Escolha o elemento que melhor corresponde à semântica do seu caso de uso — <a> para navegação, <button> para ações — e use CSS para alcançar o design visual de que precisa.
Encontre problemas como este automaticamente
O Rocket Validator analisa milhares de páginas em segundos, detetando problemas HTML em todo o seu site.