input type="image" envia o formulário: quando usar e o que pôr no lugar
O input de imagem é um botão de envio que manda as coordenadas do clique. Veja quando trocar por link ou por button, como dar nome e como fazer o hover só com CSS.
A busca do site tem uma lupa desenhada como botão, e o relatório de páginas começa a mostrar endereços como /busca?q=tenis&x=14&y=9. Em outra tela, a mesma técnica foi usada para um "Voltar" com uma seta: a pessoa clica, o formulário de cadastro é enviado pela metade e o servidor devolve erro de validação. As duas coisas têm a mesma origem: <input type="image"> parece figura, mas é um botão de envio.
A resposta curta: se a figura leva para outro endereço, use <a href>; se envia o formulário, use <button type="submit"> com a imagem ou o ícone dentro e um nome acessível. O input de imagem só faz sentido quando você realmente quer saber onde, na figura, a pessoa clicou, e isso é raríssimo.
O que o input de imagem faz de verdade
O <input type="image" src="lupa.png" alt="Buscar"> é um botão de envio com uma figura no lugar do texto. Clicar nele envia o formulário em que ele está, como qualquer type="submit". A diferença é o que vai junto: o navegador acrescenta as coordenadas do clique dentro da imagem.
Sem atributo name, os campos se chamam x e y. Com name="buscar", viram buscar.x e buscar.y. No PHP, o ponto no nome é trocado por sublinhado, e os valores aparecem como $_POST['buscar_x'] e $_POST['buscar_y']. Se o formulário usa GET, as coordenadas vão para a URL, que é exatamente a origem do &x=14&y=9 no relatório.
Essas coordenadas também não são confiáveis. Elas mudam com o zoom e com o tamanho em que a imagem foi desenhada, e quando a pessoa ativa o controle pelo teclado não há ponto clicado: o valor enviado é zero. Código que decide algo pelo x e pelo y se comporta diferente para cada pessoa.
Como escolher o elemento certo
- Pergunte o que acontece ao ativar. Vai para outro endereço? É link. Envia ou altera dados? É botão.
- Para link, use
<a href>com a imagem dentro e o texto alternativo descrevendo o destino. - Para envio, use
<button type="submit">com a imagem ou o SVG dentro e um nome: texto visível, texto escondido visualmente ouaria-label. - Para ações que não enviam (abrir um painel, limpar um campo), use
<button type="button">. Dentro de um formulário, um<button>semtypeé de envio. - Faça a troca de aparência no hover e no foco com CSS, não trocando o
srcpor JavaScript.
A busca com lupa, antes e depois
<!-- antes: envia x e y junto com a busca -->
<form action="/busca" method="get">
<input type="search" name="q">
<input type="image" src="/img/lupa.png">
</form>
<!-- depois: só o termo vai na URL -->
<form action="/busca" method="get" role="search">
<label for="campo-busca">Buscar produtos</label>
<input type="search" id="campo-busca" name="q">
<button type="submit" aria-label="Buscar">
<img src="/img/lupa.svg" alt="" width="20" height="20">
</button>
</form>
Na versão antiga, faltava até o alt, então o leitor de tela anunciava o botão pelo nome do arquivo ou não anunciava nada. Na nova, a imagem tem alt="" porque é decoração: o nome do botão vem do aria-label. Um botão com nome em dois lugares seria lido duas vezes. Os detalhes de nome em ícone estão em ícone com nome no botão e, para SVG de biblioteca, em ícone SVG com nome.
O "Voltar" que enviava o cadastro
A seta de voltar estava dentro do formulário, como input de imagem, e por isso enviava. A pergunta do Stack Overflow que deu origem a este post fazia o mesmo: envolvia o input num link para tentar navegar. Isso coloca um controle interativo dentro de outro, o que o HTML não permite, e cada navegador decide o que fazer com o clique. O certo é separar:
<form action="/cadastro" method="post">
<!-- campos -->
<a href="/carrinho">Voltar ao carrinho</a>
<button type="submit">Continuar para o pagamento</button>
</form>
O link pode ficar com cara de botão secundário, se o design pedir. O que importa é que, ao ativar, ele navegue, com teclado ou mouse, sem enviar nada. A diferença entre os dois papéis está em botão faz ação, link vai para um lugar.
Hover sem trocar a imagem por script
A troca de figura no hover era feita com JavaScript mudando o src, o que causa um piscar na primeira vez (a segunda imagem ainda não foi baixada) e não acontece no foco do teclado. Se o ícone for um SVG embutido no HTML com fill="currentColor", o CSS muda a cor do ícone e do fundo de uma vez. Se ele vier por <img>, o SVG não herda a cor da página; nesse caso, mude só o fundo e escolha um ícone que contraste com os dois estados:
button[type="submit"] {
color: #1f2937;
background: #e5e7eb;
border: 0;
padding: .5rem;
border-radius: .375rem;
}
button[type="submit"]:hover,
button[type="submit"]:focus-visible {
color: #ffffff;
background: #1d4ed8;
}
A mudança no hover precisa manter o contraste entre ícone e fundo, e não pode ser a única pista de que aquilo é clicável. O formato de botão, o cursor padrão e o rótulo já fazem esse trabalho.
Quando o input de imagem ainda serve
O caso legítimo é o original da especificação: uma imagem em que o ponto clicado importa e é processado no servidor, como um mapa em que clicar escolhe a região. Mesmo aí, há alternativas melhores hoje (uma lista de regiões, um mapa com links), porque o teclado não tem como escolher coordenadas. Se você mantiver, dê alt descritivo e ofereça outro caminho para a mesma escolha.
Erros comuns
- Usar input de imagem como link. O formulário é enviado sem querer, às vezes pela metade, e o servidor responde com erro de validação.
- Envolver o input num
<a>. Controle interativo dentro de outro é HTML inválido, e o resultado do clique varia por navegador. - Esquecer o
alt. O botão de envio fica sem nome e o leitor de tela anuncia o arquivo ou nada. - Depender do
xe doy. Mudam com o zoom e valem zero no teclado, e a lógica erra para parte das pessoas. <button>semtypedentro do formulário. O "Limpar" ou "Ver senha" também envia, porque o padrão ésubmit.- Trocar a figura no hover por JavaScript. Pisca na primeira vez e não reage ao foco.
Checklist
- Nenhum
type="image"no projeto, ou cada um tem motivo para depender das coordenadas. - Toda figura que navega é um
<a href>. - Todo envio é um
<button type="submit">com nome acessível. - Todo
<button>dentro de formulário temtypeexplícito. - Imagem decorativa dentro de botão com nome tem
alt="". - O estado de hover também aparece com
:focus-visible. - As URLs de busca nos relatórios não têm
xey.
Ative pelo teclado cada figura clicável da sua página de cadastro. Ela envia ou navega? A resposta tem de ser uma só, a mesma do clique do mouse, e tem de ser a que a figura promete.
Referência: http://pt.stackoverflow.com/questions/27780/input-type-image-com-link-e-hover