Sobre este problema HTML
O ARIA button role informa aos navegadores e tecnologias assistivas que um elemento se comporta como um botão. De acordo com a especificação WAI-ARIA, elementos com role="button" seguem as mesmas restrições de conteúdo que elementos nativos <button>. Especificamente, não devem conter conteúdo interativo como descendentes. O elemento <input> é considerado conteúdo interativo, por isso aninhá-lo dentro de qualquer elemento com role="button" é inválido.
Esta restrição existe por razões importantes 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 contém outro elemento interativo como um <input>, o utilizador enfrenta interações conflituantes — 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 lidar com eventos de foco e clique de forma imprevisível quando elementos interativos são aninhados desta forma.
A mesma regra aplica-se a elementos nativos <button>, 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 esta questão, considere estas abordagens:
-
Mova o
<input>para fora do elemento com button role e posicione-os como 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 precisa tanto de uma ação de botão como de um input, devem ser controlos separados que são agrupados visualmente 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 button role
Se quiser um botão estilo toggle que transmita 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 apenas com conteúdo fraseado não-interativo
<div role="button" tabindex="0">
<span>Click me</span>
</div>
Em caso de dúvida, mantenha elementos interativos como controlos separados e distintos em vez de os aninhar. Isto garante semântica clara, comportamento previsível entre 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.