Sobre este problema HTML
A especificação HTML define button como um elemento de conteúdo interativo que aceita conteúdo de fraseado como filhos, mas proíbe explicitamente conteúdo interativo como descendentes. Quando você adiciona um atributo tabindex a um elemento, torna-o focalizável e potencialmente interativo, o que viola esta restrição do modelo de conteúdo.
Esta regra existe por razões importantes. Um elemento button é um único controlo interativo — quando um utilizador pressiona Tab, todo o botão recebe o foco como uma unidade. Se elementos dentro do botão também tiverem tabindex, leitores de ecrã e utilizadores de teclado encontram itens focalizáveis aninhados dentro do que deveria ser um único alvo de ação. Isto cria comportamentos confusos e imprevisíveis: os utilizadores podem navegar para dentro dos elementos internos do botão sem compreender o contexto, e tecnologias assistivas podem anunciar os elementos internos separadamente, quebrando o padrão de interação esperado.
Os navegadores também podem lidar com elementos focalizáveis aninhados de forma inconsistente. Alguns podem ignorar o tabindex interno, enquanto outros podem permitir o foco no elemento aninhado mas não ativar adequadamente o manipulador de clique do botão, levando a funcionalidade quebrada.
Como corrigir
A correção mais direta é remover o atributo tabindex de quaisquer elementos dentro do button. Se o elemento interno recebeu tabindex="0" para o tornar focalizável, não precisa dele — o próprio botão já é focalizável. Se recebeu tabindex="-1" para gerir o foco programaticamente, reconsidere se essa gestão de foco é necessária dentro de um contexto de botão.
Se você genuinamente precisa de múltiplos elementos interativos na mesma área, reestruture a sua marcação para que os elementos interativos sejam irmãos em vez de aninhados dentro de um button.
Exemplos
❌ Incorreto: span com tabindex dentro de um button
<button type="button">
<span tabindex="0">Clique em mim</span>
</button>
O span tem tabindex="0", tornando-o um descendente focalizável do button. Isto viola o modelo de conteúdo.
✅ Correto: Remover tabindex do descendente
<button type="button">
<span>Clique em mim</span>
</button>
O span já não tem tabindex, portanto o button comporta-se como um único controlo focalizável.
❌ Incorreto: Múltiplos elementos focalizáveis dentro de um button
<button type="button">
<span tabindex="0" class="icon">★</span>
<span tabindex="-1" class="label">Favorito</span>
</button>
Ambos os elementos span internos têm atributos tabindex, o que é inválido independentemente do valor do tabindex.
✅ Correto: Estilizar elementos internos sem os tornar focalizáveis
<button type="button">
<span class="icon">★</span>
<span class="label">Favorito</span>
</button>
✅ Correto: Reestruturar se interações separadas forem necessárias
Se você precisar de um ícone e uma ação separada lado a lado, use elementos irmãos em vez de aninhamento:
<span class="icon" aria-hidden="true">★</span>
<button type="button">Favorito</button>
Isto mantém o botão como um elemento interativo único e limpo, enquanto coloca o ícone decorativo fora dele.
Encontre problemas como este automaticamente
O Rocket Validator analisa milhares de páginas em segundos, detetando problemas HTML em todo o seu site.