Detección de dispositivos táctiles con JavaScript
La detección táctil parece simple hasta que te encuentras frente a una Surface Pro, un iPad con Magic Keyboard o un Chromebook con pantalla táctil. Estos dispositivos híbridos rompen el supuesto de que “táctil” y “ratón” son mutuamente excluyentes, y es exactamente ahí donde la mayoría de los enfoques de detección fallan.
Este artículo va directo al grano: qué funciona realmente, qué no, y cuándo no deberías molestarte en detectar el táctil en absoluto.
Puntos clave
'ontouchstart' in windowno es confiable porque los navegadores lo exponen de manera inconsistente, incluso en dispositivos sin pantalla táctil.navigator.maxTouchPoints > 0es la verificación JavaScript simple más confiable para la capacidad táctil reportada en navegadores modernos.- Las media queries CSS de puntero (
pointer,any-pointer,hover) manejan la mayoría de las adaptaciones de UI sin necesidad de JavaScript. - La API de Pointer Events y su propiedad
pointerTypete permiten detectar el método de entrada actual del usuario, lo cual es mucho más útil en dispositivos híbridos que una verificación única al cargar la página.
Por qué 'ontouchstart' in window no es suficiente
Durante años, los desarrolladores verificaban 'ontouchstart' in window como una forma rápida de detectar capacidad táctil. El problema es que los navegadores exponen esta propiedad de manera inconsistente. Algunos navegadores de escritorio en Windows 8+ la reportan como true incluso sin pantalla táctil. Chrome ha alternado su comportamiento a través de versiones. Es una señal poco confiable.
Depender únicamente de ontouchstart significa que estás detectando el comportamiento del navegador, no la capacidad real del hardware.
navigator.maxTouchPoints: la línea base más confiable
La propiedad JavaScript más confiable para detectar soporte táctil hoy en día es navigator.maxTouchPoints. Devuelve el número máximo de puntos de contacto táctil simultáneos que soporta el dispositivo. Un valor mayor que cero significa que el hardware reporta capacidad táctil.
function hasTouchSupport() {
return navigator.maxTouchPoints > 0
}
Esto es parte de la especificación de Pointer Events y está soportado en todos los navegadores modernos: Chrome, Firefox, Safari y Edge. Es limpio, legible y no depende del rastreo de manejadores de eventos.
Nota:
navigator.msMaxTouchPointsera el equivalente de la era IE. No lo necesitas a menos que estés manteniendo código heredado.
Cuándo las media queries CSS de puntero son la mejor herramienta
Para la mayoría de las adaptaciones de UI, no necesitas JavaScript en absoluto. Las media queries CSS de puntero te permiten ajustar el estilo basándote en la precisión del dispositivo de entrada principal.
/* Apunta a dispositivos donde el puntero principal es grueso (p. ej., dedo) */
@media (pointer: coarse) {
.btn {
min-height: 48px;
}
}
/* Apunta a cualquier puntero disponible que sea grueso, incluyendo entradas secundarias */
@media (any-pointer: coarse) {
.tooltip {
display: none;
}
}
/* Apunta a dispositivos donde el hover no está disponible de manera confiable */
@media (hover: none) {
.dropdown:hover .menu {
display: none;
}
}
La diferencia entre pointer y any-pointer importa en dispositivos híbridos. pointer: coarse refleja solo la entrada principal. any-pointer: coarse devuelve verdadero si cualquier entrada conectada es gruesa, útil cuando un dispositivo tiene tanto ratón como pantalla táctil.
Discover how at OpenReplay.com.
Pointer Events vs. Touch Events
Pointer Events es el modelo moderno y unificado para manejar entrada de ratón, táctil y stylus en JavaScript. En lugar de mantener manejadores separados de touchstart y mousedown, escribes uno solo:
element.addEventListener('pointerdown', (e) => {
if (e.pointerType === 'touch') {
// Manejar entrada táctil
} else if (e.pointerType === 'mouse') {
// Manejar entrada de ratón
}
})
La propiedad pointerType te dice exactamente qué está haciendo el usuario en este momento, no de qué es teóricamente capaz su dispositivo. Esta es la distinción que más importa en dispositivos híbridos.
Los Touch Events heredados (touchstart, touchmove, touchend) todavía están soportados en la mayoría de los navegadores pero no están disponibles en todos los entornos y no cubren entrada de ratón o stylus. Prefiere Pointer Events para código nuevo.
El problema de los dispositivos híbridos
Un usuario en un portátil con capacidad táctil podría iniciar una sesión con ratón y luego alcanzar y tocar la pantalla. Cualquier detección que hagas al cargar la página ya está desactualizada.
En lugar de fijar un único resultado de detección, escucha eventos pointerdown y lee e.pointerType dinámicamente. Esto te permite adaptar la UI basándote en lo que el usuario está haciendo realmente, no en lo que su dispositivo soporta en teoría.
Qué usar y cuándo
| Objetivo | Enfoque recomendado |
|---|---|
| Ajustar tamaños de botones o áreas táctiles | CSS @media (pointer: coarse) |
| Suprimir UI solo con hover | CSS @media (hover: none) |
| Verificar capacidad de hardware táctil en JS | navigator.maxTouchPoints > 0 |
| Manejar eventos de entrada en todos los tipos | API de Pointer Events |
| Detectar tipo de entrada actual dinámicamente | event.pointerType en pointerdown |
Conclusión
Omite completamente el rastreo del user agent. Para ajustes de UI, las media queries CSS de puntero manejan la mayoría de los casos sin una sola línea de JavaScript. Cuando sí necesites JavaScript, navigator.maxTouchPoints te da una señal confiable del hardware, y la API de Pointer Events te da contexto de entrada en tiempo real. Juntos, cubren toda la gama de dispositivos modernos, incluyendo los híbridos que hacen que la detección simple no sea confiable.
Preguntas frecuentes
Sí. navigator.maxTouchPoints es parte de la especificación de Pointer Events y está soportado en Chrome, Firefox, Safari y Edge. Generalmente devuelve cero en dispositivos que no reportan soporte táctil, y un entero positivo en dispositivos con capacidad táctil. Es la verificación de propiedad única más confiable disponible en JavaScript hoy en día para detectar soporte táctil.
Las cadenas de user agent no son confiables para determinar capacidades de entrada. Identifican el navegador y el sistema operativo, no el hardware. Un portátil Windows y una tablet Windows pueden compartir la misma cadena de user agent a pesar de tener métodos de entrada muy diferentes. La detección de características a través de maxTouchPoints o media queries CSS es mucho más precisa.
Sí. La API de Pointer Events proporciona una propiedad pointerType en eventos como pointerdown. Su valor es touch, mouse o pen dependiendo de la entrada que se esté usando en ese momento. Esto es más útil que una verificación de capacidad única, especialmente en dispositivos híbridos donde los usuarios cambian entre entradas.
La media query pointer apunta solo al dispositivo de entrada principal. La query any-pointer devuelve verdadero si cualquier entrada disponible coincide con la condición. En un portátil con trackpad y pantalla táctil, pointer coarse puede ser falso porque el trackpad es principal, pero any-pointer coarse sería verdadero porque la pantalla táctil califica.
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.