Skip to main content
Validação HTML

O elemento “button” não deve aparecer como descendente de um elemento com o atributo “role=button”.

Sobre este problema HTML

O atributo role="button" informa tecnologias assistivas como leitores de ecrã que um elemento se comporta como um botão — um widget usado para executar ações como submeter um formulário, abrir um diálogo, ou desencadear um comando. Quando um elemento <button> aparece dentro de um elemento com role="button", o resultado é um controlo interativo aninhado. A especificação HTML proíbe explicitamente isto porque conteúdo interativo não deve ser aninhado dentro de outro conteúdo interativo.

Este aninhamento causa problemas reais. Os leitores de ecrã podem anunciar o elemento exterior como um botão mas falhar ao reconhecer ou alcançar o <button> interior. Os utilizadores de teclado podem não conseguir focar ou ativar o controlo interior. Diferentes navegadores lidam com a situação de forma inconsistente — alguns podem ignorar completamente um dos controlos, outros podem disparar eventos no elemento errado. O resultado final é uma interface que está quebrada para muitos utilizadores.

Este problema surge comummente em alguns cenários:

  • Um <div> ou <span> recebe role="button" e depois um <button> é colocado dentro dele para fins de estilo ou gestão de cliques.
  • Uma biblioteca de componentes envolve conteúdo num contentor role="button", e um programador adiciona um <button> dentro sem perceber o conflito.
  • Um cartão personalizado ou item de lista é tornado clicável com role="button", mas também contém botões de ação dentro dele.

A correção depende da sua intenção. Se o elemento exterior é o controlo interativo pretendido, remova o <button> interior e gira as interações no elemento exterior. Se o <button> interior é o controlo pretendido, remova role="button" do ancestral. Se ambos precisam de ser independentemente clicáveis, reestruture a marcação para que nenhum seja descendente do outro.

Exemplos

❌ Incorreto: <button> dentro de um elemento com role="button"

<div role="button" tabindex="0" onclick="handleClick()">
  <button type="button">Click me</button>
</div>

Isto é inválido porque o <button> é um descendente do <div> que tem role="button".

✅ Opção de correção 1: Use apenas o elemento <button>

Se o <button> interior é o controlo real, remova role="button" do wrapper:

<div>
  <button type="button" onclick="handleClick()">Click me</button>
</div>

✅ Opção de correção 2: Use apenas o elemento exterior role="button"

Se o elemento exterior é o controlo interativo pretendido, remova o <button> interior:

<div role="button" tabindex="0" onclick="handleClick()">
  Click me
</div>

Note que ao usar role="button" num elemento que não é <button>, você também deve gerir eventos de teclado (Enter e Space) manualmente. Um <button> nativo fornece isto gratuitamente, portanto prefira a opção 1 quando possível.

❌ Incorreto: Cartão clicável contendo botões de ação

<div role="button" tabindex="0" class="card">
  <h3>Item title</h3>
  <p>Description text</p>
  <button type="button">Delete</button>
</div>

✅ Correção: Separe o link do cartão dos botões de ação

<div class="card">
  <h3><button type="button" class="card-link">Item title</button></h3>
  <p>Description text</p>
  <button type="button">Delete</button>
</div>

Nesta abordagem, a ação principal do cartão é gerida por um <button> no título, enquanto o botão “Delete” permanece um controlo independente. Nenhum está aninhado dentro do outro, e ambos são acessíveis para utilizadores de teclado e leitores de ecrã.

Encontre problemas como este automaticamente

O Rocket Validator analisa milhares de páginas em segundos, detetando problemas HTML em todo o seu site.

Ajude-nos a melhorar os nossos guias

Este guia foi útil?

Pronto para validar os seus sites?
Comece o seu teste gratuito hoje.