Sobre este problema HTML
O role ARIA button informa os navegadores e tecnologias assistivas que um elemento se comporta como um botão. Segundo a especificação WAI-ARIA, elementos com role="button" seguem as mesmas restrições de conteúdo que elementos <button> nativos. Especificamente, não devem conter conteúdo interativo como descendentes. O elemento <input> é considerado conteúdo interativo, pelo que aninhá-lo dentro de qualquer elemento com role="button" é inválido.
Esta restrição existe por importantes razões de acessibilidade e usabilidade. Quando um leitor de ecrã encontra um elemento com role="button", anuncia-o como um único controlo acionável. Se esse botão contiver outro elemento interativo como um <input>, o utilizador enfrenta interações conflituosas — ativar o elemento deve desencadear a ação do botão ou interagir com o input? Esta ambiguidade confunde tanto as tecnologias assistivas como os utilizadores. Os navegadores também podem gerir eventos de foco e clique de forma imprevisível quando elementos interativos estão aninhados desta forma.
A mesma regra aplica-se a elementos <button> nativos, elementos <a> com um href, e qualquer outro elemento que já seja interativo. Adicionar role="button" a um <div> ou <span> eleva-o ao mesmo estatuto, pelo que as mesmas restrições de aninhamento se aplicam.
Para corrigir este problema, considere estas abordagens:
-
Mova o
<input>para fora do elemento com role de botão e posicione-os como elementos irmãos. -
Substitua o
<input>por conteúdo não interativo como um<span>estilizado para parecer o controlo desejado, com atributos ARIA apropriados para transmitir o estado. - Repense a estrutura do componente — se precisar tanto de uma ação de botão como de um input, devem ser controlos separados que estão visualmente agrupados mas não aninhados.
Exemplos
❌ Inválido: <input> aninhado dentro de um elemento com role="button"
<div role="button" tabindex="0">
<input type="checkbox" />
Accept terms
</div>
❌ Inválido: <input> aninhado dentro de um <button> nativo
<button>
<input type="text" />
Search
</button>
✅ Válido: Separe o <input> e o botão em elementos irmãos
<label>
<input type="checkbox" />
Accept terms
</label>
<button>Submit</button>
✅ Válido: Use conteúdo não interativo dentro do elemento com role de botão
Se quiser um botão estilo toggle que transmita o estado marcado/desmarcado, use atributos ARIA no próprio botão em vez de incorporar um <input>:
<div role="button" tabindex="0" aria-pressed="false">
<span aria-hidden="true">☐</span>
Accept terms
</div>
✅ Válido: Use um <label> e <input> junto com um botão
<div>
<label>
<input type="checkbox" />
Accept terms
</label>
<div role="button" tabindex="0">Continue</div>
</div>
✅ Válido: Botão com apenas conteúdo frásico não interativo
<div role="button" tabindex="0">
<span>Click me</span>
</div>
Em caso de dúvida, mantenha os elementos interativos como controlos separados e distintos em vez de aninhá-los. Isto garante semântica clara, comportamento previsível em todos os navegadores, e uma boa experiência para utilizadores de tecnologias assistivas.
Encontre problemas como este automaticamente
O Rocket Validator analisa milhares de páginas em segundos, detetando problemas HTML em todo o seu site.