Sobre este problema HTML
A especificação HTML define regras rigorosas sobre quais elementos podem estar aninhados dentro de outros. O elemento <a> é classificado como conteúdo interativo, e o seu modelo de conteúdo proíbe explicitamente outro conteúdo interativo como descendente. Elementos com role="button" — seja um <button> nativo ou qualquer elemento com o ARIA role — também são interativos. Aninhar um dentro do outro cria uma situação ambígua: deve um clique ativar o link ou o button?
Isto é importante por várias razões importantes:
- Acessibilidade: Leitores de ecrã e tecnologias assistivas dependem de uma hierarquia de elementos clara e não ambígua. Quando um button está dentro de um link, o role anunciado torna-se confuso — os utilizadores podem ouvir tanto um link como um button, ou a tecnologia assistiva pode expor apenas um deles, escondendo a funcionalidade do outro.
- Comportamento imprevisível: Os navegadores lidam com elementos interativos aninhados de forma inconsistente. Alguns podem separar os elementos no DOM, enquanto outros podem suprimir eventos de clique. Isto leva a comportamentos danificados ou não confiáveis em diferentes navegadores.
- Conformidade com padrões: O WHATWG HTML Living Standard e a especificação HTML do W3C proíbem explicitamente este padrão de aninhamento.
Para corrigir este problema, decida o que o elemento deve realmente fazer. Se navegar para um URL, use um elemento <a>. Se executar uma ação (como submeter um formulário ou acionar JavaScript), use um <button>. Se precisar de ambos os estilos visuais, use CSS para dar estilo a um elemento para parecer o outro.
Exemplos
❌ Incorreto: Elemento com role="button" dentro de um <a>
<a href="/dashboard">
<span role="button">Ir para o Painel</span>
</a>
O <span> com role="button" é conteúdo interativo aninhado dentro do elemento <a> interativo.
❌ Incorreto: <button> dentro de um <a>
<a href="/settings">
<button>Abrir Definições</button>
</a>
Um elemento <button> é inerentemente interativo e não deve aparecer dentro de um <a>.
✅ Correto: Use um link com estilo de button
Se o propósito é navegação, use o elemento <a> e dê-lhe estilo com CSS:
<a href="/dashboard" class="btn">Ir para o Painel</a>
✅ Correto: Use um button que navega via JavaScript
Se precisar de um button que também navega, trate a navegação em JavaScript:
<button type="button" onclick="location.href='/dashboard'">Ir para o Painel</button>
✅ Correto: Coloque elementos lado a lado
Se realmente precisar tanto de um link como de um button, mantenha-os como irmãos em vez de aninhar um dentro do outro:
<div class="actions">
<a href="/dashboard">Ir para o Painel</a>
<button type="button">Guardar Preferência</button>
</div>
✅ Correto: Link com estilo de button usando ARIA (quando apropriado)
Se o elemento navega mas você quer que as tecnologias assistivas o anunciem como um button, pode aplicar role="button" diretamente ao elemento — apenas não o aninhe dentro de um <a>:
<span role="button" tabindex="0" onclick="location.href='/dashboard'">
Ir para o Painel
</span>
Note que usar role="button" num elemento não interativo como <span> requer que você também adicione tabindex="0" para focabilidade do teclado e lide com eventos keydown para as teclas Enter e Espaço. Na maioria dos casos, um elemento <a> ou <button> nativo é a melhor escolha.
Encontre problemas como este automaticamente
O Rocket Validator analisa milhares de páginas em segundos, detetando problemas HTML em todo o seu site.