Detecção de Dispositivos Touch com JavaScript
A detecção de toque parece simples até você se deparar com um Surface Pro, um iPad com Magic Keyboard ou um Chromebook com tela sensível ao toque. Esses dispositivos híbridos quebram a suposição de que “toque” e “mouse” são mutuamente exclusivos—e é exatamente aí que a maioria das abordagens de detecção falha.
Este artigo vai direto ao ponto: o que realmente funciona, o que não funciona e quando você não deveria se preocupar em detectar toque.
Principais Conclusões
'ontouchstart' in windownão é confiável porque os navegadores o expõem de forma inconsistente, mesmo em dispositivos sem tela sensível ao toque.navigator.maxTouchPoints > 0é a verificação JavaScript simples mais confiável para capacidade de toque reportada em navegadores modernos.- Media queries CSS de ponteiro (
pointer,any-pointer,hover) lidam com a maioria das adaptações de UI sem necessidade de JavaScript. - A API Pointer Events e sua propriedade
pointerTypepermitem detectar o método de entrada atual do usuário, o que é muito mais útil em dispositivos híbridos do que uma verificação única no carregamento da página.
Por Que 'ontouchstart' in window Não É Suficiente
Por anos, desenvolvedores verificavam 'ontouchstart' in window como uma forma rápida de detectar capacidade de toque. O problema é que os navegadores expõem essa propriedade de forma inconsistente. Alguns navegadores desktop no Windows 8+ reportam como true mesmo sem uma tela sensível ao toque. O Chrome alternou seu comportamento ao longo das versões. É um sinal impreciso.
Confiar apenas em ontouchstart significa que você está detectando o comportamento do navegador, não a capacidade real do hardware.
navigator.maxTouchPoints: A Linha de Base Mais Confiável
A propriedade JavaScript mais confiável para detectar suporte a toque atualmente é navigator.maxTouchPoints. Ela retorna o número máximo de pontos de contato de toque simultâneos que o dispositivo suporta. Um valor maior que zero significa que o hardware reporta capacidade de toque.
function hasTouchSupport() {
return navigator.maxTouchPoints > 0
}
Isso faz parte da especificação Pointer Events e é suportado em todos os navegadores modernos—Chrome, Firefox, Safari e Edge. É limpo, legível e não depende de detecção de manipuladores de eventos.
Nota:
navigator.msMaxTouchPointsera o equivalente da era do IE. Você não precisa dele a menos que esteja mantendo código legado.
Quando Media Queries CSS de Ponteiro São a Ferramenta Melhor
Para a maioria das adaptações de UI, você não precisa de JavaScript. Media queries CSS de ponteiro permitem ajustar o estilo com base na precisão do dispositivo de entrada primário.
/* Segmenta dispositivos onde o ponteiro primário é grosseiro (ex: dedo) */
@media (pointer: coarse) {
.btn {
min-height: 48px;
}
}
/* Segmenta qualquer ponteiro disponível que seja grosseiro, incluindo entradas secundárias */
@media (any-pointer: coarse) {
.tooltip {
display: none;
}
}
/* Segmenta dispositivos onde hover não está disponível de forma confiável */
@media (hover: none) {
.dropdown:hover .menu {
display: none;
}
}
A diferença entre pointer e any-pointer importa em dispositivos híbridos. pointer: coarse reflete apenas a entrada primária. any-pointer: coarse retorna verdadeiro se qualquer entrada conectada for grosseira—útil quando um dispositivo tem tanto mouse quanto tela sensível ao toque.
Discover how at OpenReplay.com.
Pointer Events vs. Touch Events
Pointer Events são o modelo moderno e unificado para lidar com entrada de mouse, toque e caneta em JavaScript. Em vez de manter manipuladores separados de touchstart e mousedown, você escreve um:
element.addEventListener('pointerdown', (e) => {
if (e.pointerType === 'touch') {
// Lidar com entrada por toque
} else if (e.pointerType === 'mouse') {
// Lidar com entrada por mouse
}
})
A propriedade pointerType informa exatamente o que o usuário está fazendo neste momento—não o que seu dispositivo é teoricamente capaz de fazer. Essa é a distinção que mais importa em dispositivos híbridos.
Touch Events legados (touchstart, touchmove, touchend) ainda são suportados na maioria dos navegadores, mas não estão disponíveis em todos os ambientes e não cobrem entrada de mouse ou caneta. Prefira Pointer Events para código novo.
O Problema dos Dispositivos Híbridos
Um usuário em um laptop com toque pode iniciar uma sessão com mouse e depois tocar na tela. Qualquer detecção que você faça no carregamento da página já está desatualizada.
Em vez de fixar um único resultado de detecção, escute eventos pointerdown e leia e.pointerType dinamicamente. Isso permite adaptar a UI com base no que o usuário está realmente fazendo, não no que seu dispositivo suporta em teoria.
O Que Usar e Quando
| Objetivo | Abordagem Recomendada |
|---|---|
| Ajustar tamanhos de botões ou áreas de toque | CSS @media (pointer: coarse) |
| Suprimir UI exclusiva de hover | CSS @media (hover: none) |
| Verificar capacidade de hardware touch em JS | navigator.maxTouchPoints > 0 |
| Lidar com eventos de entrada em todos os tipos | API Pointer Events |
| Detectar tipo de entrada atual dinamicamente | event.pointerType em pointerdown |
Conclusão
Evite completamente a detecção por user agent. Para ajustes de UI, media queries CSS de ponteiro lidam com a maioria dos casos sem uma única linha de JavaScript. Quando você precisar de JavaScript, navigator.maxTouchPoints fornece um sinal de hardware confiável, e a API Pointer Events fornece contexto de entrada em tempo real. Juntos, eles cobrem toda a gama de dispositivos modernos—incluindo os híbridos que tornam a detecção simples não confiável.
Perguntas Frequentes
Sim. navigator.maxTouchPoints faz parte da especificação Pointer Events e é suportado no Chrome, Firefox, Safari e Edge. Geralmente retorna zero em dispositivos que não reportam suporte a toque, e um número inteiro positivo em dispositivos com capacidade de toque. É a verificação de propriedade única mais confiável disponível em JavaScript hoje para detectar suporte a toque.
Strings de user agent não são confiáveis para determinar capacidades de entrada. Elas identificam o navegador e sistema operacional, não o hardware. Um laptop Windows e um tablet Windows podem compartilhar a mesma string de user agent apesar de terem métodos de entrada muito diferentes. Detecção de recursos através de maxTouchPoints ou media queries CSS é muito mais precisa.
Sim. A API Pointer Events fornece uma propriedade pointerType em eventos como pointerdown. Seu valor é touch, mouse ou pen dependendo da entrada sendo usada naquele momento. Isso é mais útil do que uma verificação única de capacidade, especialmente em dispositivos híbridos onde os usuários alternam entre entradas.
A media query pointer segmenta apenas o dispositivo de entrada primário. A query any-pointer retorna verdadeiro se qualquer entrada disponível corresponder à condição. Em um laptop com trackpad e tela sensível ao toque, pointer coarse pode ser falso porque o trackpad é primário, mas any-pointer coarse seria verdadeiro porque a tela sensível ao toque se qualifica.
Complete picture for complete understanding
Capture every clue your frontend is leaving so you can instantly get to the root cause of any issue with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.
Check our GitHub repo and join the thousands of developers in our community.