Origem do Atraso no Evento de Clique em Móveis
Em navegadores móveis, há um atraso típico de cerca de 300 milissegundos ao acionar o evento click. Esse comportamento foi implementado historicamente para distinguir entre um simples toque e uma ação de duplo toque (double tap), que normalmente realiza o zoom na página. Devido a essa necessidade de verificação, o navegador aguarda brevemente antes de confirmar se é um clique único. Essa latência prejudica a experiência de resposta imediata em interfaces sensíveis ao toque.
Estratégias para Mitigar o Atraso
- Desativar zoom com viewport meta: ```
Embora elimine o atraso, impede que o usuário amplie o conteúdo, afetando acessibilidade. - Definir largura do viewport como largura do dispositivo: ```
Em versões recantes do Chrome para Android (32+), esse ajuste dispensa os 300ms de espera. - Usar a propriedade CSS
touch-action: Ao definirtouch-action: manipulation(ou-ms-touch-action: manipulationno IE10), o navegador suprime o reconhecimento de duplo toque em elemantos interativos como botões e links, eliminando o atraso. ``` button, a { touch-action: manipulation; } - Eventos personalizados de toque (ex: Zepto.tap): Baseia-se nos eventos
touchstartetouchendpara simular cliques. Contudo, pode gerar problemas de "passagem de toque" (event ghosting), onde elementos sobpostos recebem cliques indesejados. - Uso do FastClick: Esta biblioteca monitora eventos de toque e dispara imediatamente um evento de clique simulado via
dispatchEvent, cancelando o clique nativo posterior compreventDefault()quando este for emitido após o atraso padrão.
Implementação do FastClick
Para integrar o FastClick em projetos tradicionais:
<script type="application/javascript" src="/caminho/fastclick.js"></script>
<script>
if ('addEventListener' in document) {
document.addEventListener('DOMContentLoaded', function() {
FastClick.attach(document.body);
}, false);
}
</script>
Em aplicações Vue.js, instale via npm:
npm install fastclick --save
Em seguida, ative-o no ponto de entrada da aplicação (ex: main.js):
import FastClick from 'fastclick';
FastClick.attach(document.body);
Quando o FastClick Não é Necesssário
- Navegadores desktop não são afetados pelo atraso de 300ms, portanto o FastClick não adiciona ouvintes nesses ambientes.
- No Chrome para Android 32+, com
width=device-widthno viewport, o clique é imediato. - Se
user-scalable=noestiver presente no meta viewport, o Chrome também ignora o atraso. - Em navegadores baseados em Trident (IE10/11), usar
touch-action: manipulationjá resolve o problema sem bibliotecas externas.
Problemas Conhecidos e Correções
Um bug relatado em dispositivos iOS (especialmente versões anteriores ao iOS 11) ocorre ao clicar em campos de entrada após pressionar "Concluído" no teclado virtual: o foco no input exige toque prolongado, pois o FastClick interfere no ciclo natural de foco.
A correção envolve modificar o método focus dentro do código-fonte do FastClick:
FastClick.prototype.focus = function(elementoAlvo) {
if (deviceIsIOS && elementoAlvo.setSelectionRange &&
['date', 'time', 'month'].indexOf(elementoAlvo.type) === -1) {
const tamanho = elementoAlvo.value.length;
elementoAlvo.setSelectionRange(tamanho, tamanho);
}
elementoAlvo.focus(); // Força foco mesmo em iOS atualizado
};
Alternativamente, pode-se adicionar manualmente um listener de touchend em inputs específicos:
document.querySelectorAll('input, textarea').forEach(el => {
el.addEventListener('touchend', function(e) {
e.preventDefault();
this.focus();
}, false);
});
Essa abordagem evita dependência total do FastClick para entradas de texto.