Sobre este problema HTML
O elemento <button> tem um modelo de conteúdo estrito definido pelo WHATWG HTML Living Standard: aceita conteúdo de fraseamento, mas com a exclusão explícita de conteúdo interativo. O elemento <input> é classificado como conteúdo interativo, o que significa que aninhá-lo dentro de um <button> produz HTML inválido e despoleta este erro do validador W3C.
Por que isto é um problema
Comportamento imprevisível do navegador: Quando elementos interativos são aninhados dentro de um <button>, os navegadores têm de descobrir que elemento deve receber interações do utilizador como cliques, foco e entrada de teclado. Diferentes navegadores lidam com isto de forma diferente — alguns podem ignorar completamente o <input> interno, enquanto outros podem produzir comportamento confuso onde os cliques são absorvidos pelo <button> antes de chegarem ao <input>.
Problemas de acessibilidade: Leitores de ecrã e outras tecnologias assistivas esperam que um <button> contenha texto descritivo ou conteúdo de fraseamento simples, não outros controlos de formulário. Aninhar um <input> dentro de um <button> cria uma experiência confusa e potencialmente inutilizável para utilizadores que dependem de tecnologia assistiva. A relação entre os dois controlos torna-se ambígua — o utilizador está a interagir com o botão ou com o input?
Conformidade com os padrões: HTML válido é a base para renderização e comportamento consistentes entre navegadores e dispositivos. Usar aninhamento inválido pode levar a bugs subtis que são difíceis de diagnosticar, especialmente quando os navegadores atualizam o seu comportamento de análise.
Outros elementos que não pode aninhar dentro de <button>
A restrição aplica-se a todo o conteúdo interativo, não apenas a <input>. Também não pode colocar estes elementos dentro de um <button>:
-
<a>(com um atributohref) -
<button> -
<select> -
<textarea> -
<label> -
<audio>e<video>(comcontrols) -
<embed>,<iframe>,<object> -
Qualquer elemento com um atributo
tabindex
Como corrigir
A correção é direta: mova o <input> para fora do <button> para que sejam elementos irmãos. Envolva-os num <form>, <div>, ou outro contentor adequado, e use CSS para obter qualquer layout visual desejado.
Exemplos
❌ Inválido: <input> aninhado dentro de <button>
<button>
Submit
<input type="text" name="example">
</button>
Isto despoleta o erro porque <input> é conteúdo interativo colocado dentro de um <button>.
✅ Corrigido: <input> e <button> como irmãos
<form>
<input type="text" name="example">
<button type="submit">Submit</button>
</form>
Ambos os elementos são filhos diretos do <form>, tornando a marcação válida e os controlos independentemente acessíveis.
❌ Inválido: <input> oculto dentro de <button>
Pode pensar que um input oculto está bem porque não é visualmente interativo, mas <input type="hidden"> continua a ser um elemento <input> e ainda está proibido dentro de <button>:
<button type="submit">
Save
<input type="hidden" name="action" value="save">
</button>
✅ Corrigido: <input> oculto movido para fora de <button>
<form>
<input type="hidden" name="action" value="save">
<button type="submit">Save</button>
</form>
❌ Inválido: Checkbox dentro de um <button> para um efeito de alternância
<button class="toggle">
<input type="checkbox" name="darkmode"> Dark Mode
</button>
✅ Corrigido: Use um <label> em vez disso
Se a intenção é uma alternância clicável, um <label> emparelhado com uma checkbox obtém o mesmo resultado visual com marcação válida e acessível:
<label class="toggle">
<input type="checkbox" name="darkmode"> Dark Mode
</label>
Alternativamente, se realmente precisa de um botão que alterne estado, use JavaScript com o atributo aria-pressed em vez de incorporar uma checkbox:
<button type="button" class="toggle" aria-pressed="false">
Dark Mode
</button>
Mantenha <input> e <button> como elementos separados e irmãos. Se precisar que apareçam visualmente agrupados, use CSS para layout e estilização em vez de aninhar um elemento interativo dentro de outro.
Encontre problemas como este automaticamente
O Rocket Validator analisa milhares de páginas em segundos, detetando problemas HTML em todo o seu site.