Consulta de medios para detectar si el dispositivo tiene pantalla táctil

122

¿Cuál es la forma más segura, utilizando consultas de medios, para hacer que algo suceda cuando no está en un dispositivo con pantalla táctil? Si no hay forma, ¿sugiere usar una solución de JavaScript como !window.Toucho Modernizr?

JJJollyjim
fuente
2
Avance rápido hasta 2018, CSS ahora puede hacerlo de forma nativa stackoverflow.com/a/50285058/1717735
Buzut el

Respuestas:

37

Sugeriría usar modernizr y sus funciones de consulta de medios.

if (Modernizr.touch){
   // bind to touchstart, touchmove, etc and watch `event.streamId`
} else {
   // bind to normal click, mousemove, etc
}

Sin embargo, usando CSS, hay pseudo clases como, por ejemplo, en Firefox. Puede usar : -moz-system-metric (táctil) . Pero estas características no están disponibles para todos los navegadores.

Para dispositivos Apple , puede usar de manera simple:

if(window.TouchEvent) {
   //.....
}

Especialmente para Ipad:

if(window.Touch) {
    //....
}

Pero, estos no funcionan en Android .

Modernizr ofrece capacidades de detección de características, y la detección de características es una buena forma de codificar, en lugar de codificar en función de los navegadores.

Elementos táctiles de estilo

Modernizer agrega clases a la etiqueta HTML para este propósito exacto. En este caso, touchy no-touchpor lo que puede estilo de su tacto aspectos relacionados con el prefijo sus selectores con .Toque. por ej .touch .your-container. Créditos: Ben Swinburne

Starx
fuente
¿Estoy en lo cierto al pensar que ninguna clase de psedo funciona con todos los dispositivos / navegadores modernos?
JJJollyjim
@ JJ56, Sí, no todos los navegadores admiten pseudo clases táctiles. Pero ahí es donde modernizrserá perfecto :)
Starx
18
La Modernizr.touchprueba solo indica si el navegador admite eventos táctiles, lo que no necesariamente refleja un dispositivo con pantalla táctil. Por ejemplo, los teléfonos Palm Pre / WebOS (touch) no admiten eventos táctiles y, por lo tanto, no pasan esta prueba.
numediaweb
55
Solo para agregar a esto, si está incluyendo modernizador de todos modos; Modernizer agrega clases a la etiqueta del cuerpo para este propósito exacto. En este caso, touchy no-touchpor lo que puede el estilo de su tacto aspectos relacionados con el prefijo sus selectores con .touch. Por ejemplo.touch .your-container
Ben Swinburne el
2
Para mí, parece que modernizr agrega clase táctil a la etiqueta html, no a la etiqueta del cuerpo.
Robin Cox
162

En realidad, hay una propiedad para esto en el borrador de consulta de medios CSS4 .

La función de medios 'puntero' se utiliza para consultar sobre la presencia y precisión de un dispositivo señalador, como un mouse. Si un dispositivo tiene múltiples mecanismos de entrada, se recomienda que el UA informe las características del dispositivo señalador menos capaz de los mecanismos de entrada primarios. Esta consulta de medios toma los siguientes valores:

'ninguno'
: el mecanismo de entrada del dispositivo no incluye un dispositivo señalador.

'grueso'
: el mecanismo de entrada del dispositivo incluye un dispositivo señalador de precisión limitada.

'fino'
: el mecanismo de entrada del dispositivo incluye un dispositivo señalador preciso.

Esto se usaría como tal:

/* Make radio buttons and check boxes larger if we have an inaccurate pointing device */
@media (pointer:coarse) {
    input[type="checkbox"], input[type="radio"] {
        min-width:30px;
        min-height:40px;
        background:transparent;
    }
}

También encontré un boleto en el proyecto Chromium relacionado con esto.

La compatibilidad del navegador se puede probar en Quirksmode . Estos son mis resultados (22 de enero de 2013):

  • Chrome / Win: funciona
  • Chrome / iOS: no funciona
  • Safari / iOS6: no funciona
Znarkus
fuente
3
¿Cómo puede ser esta la respuesta con más puntos cuando la solución proporcionada no funciona incluso de acuerdo con el póster?
erdomester
55
El soporte del navegador para esto ya no es tan malo: Edge, Chrome, Safari, iOS y Android. Ver: caniuse.com/#feat=css-media-interaction
Josa
3
Buena respuesta. Además: developer.mozilla.org/en-US/docs/Web/CSS/@media/hover
aross
Funciona para mí;) ¡Gracias por investigar esto!
Verri
51

Las soluciones CSS no parecen estar ampliamente disponibles a mediados de 2013. En lugar...

  1. Nicholas Zakas explica que Modernizr aplica una no-touchclase CSS cuando el navegador no admite el tacto.

  2. O detecte en JavaScript con un código simple, lo que le permite implementar su propia solución tipo Modernizr:

    <script>
        document.documentElement.className += 
        (("ontouchstart" in document.documentElement) ? ' touch' : ' no-touch');
    </script>

    Entonces puedes escribir tu CSS como:

    .no-touch .myClass {
        ...
    }
    .touch .myClass {
        ...
    }
Simon East
fuente
El segundo es muy lindo. ¡Funciona un encanto para mí! Gracias.
Garavani
@ bjb568 Gracias por la edición sugerida, que es una alternativa más moderna, pero como solo funciona en IE 10 y superior, creo que es mejor mantener esta versión por el momento.
Simon East
Parece que esa clase estaría en la etiqueta html; lo que significaría que está deshabilitado por defecto cuando se usa CSP.
Leo
35

Los tipos de medios no le permiten detectar capacidades táctiles como parte del estándar:

http://www.w3.org/TR/css3-mediaqueries/

Por lo tanto, no hay forma de hacerlo consistentemente a través de CSS o consultas de medios, tendrá que recurrir a JavaScript.

No es necesario usar Modernizr, solo puede usar JavaScript simple:

<script type="text/javascript">
    var is_touch_device = 'ontouchstart' in document.documentElement;
    if(is_touch_device) alert("touch is enabled!");
</script>
Alex W
fuente
AFAIK, window.touch&& window.TouchEventsolo funciona para dispositivos Apple.
Starx
22
@vsync Modernizr es una excelente manera de poner todas las pruebas útiles para los desarrolladores en una biblioteca mantenida, para que no tengan que buscar en Google cada vez que necesiten probar una función específica, como eventos táctiles y tener que encontrar esta página. Para su información, hay una versión personalizada de Modernizr que puede personalizar con las pruebas que desee. Es una excelente manera de probar características siempre de la misma manera entre proyectos, ya sea que use la sintaxis JS (es decir: Modernizr.touch) o las clases CSS (.touch .my-element {}). Creo que es un insulto a la inteligencia humana el no reconocer que podemos hacer cosas sin reinventar la rueda cada vez.
Alejandro García Iglesias
11
Bueno, he trabajado en cientos de proyectos y nunca he necesitado tal cosa, en la mayoría de los casos todo lo que necesitas es un conjunto muy pequeño de pruebas, nunca más de 5 diría (en la mayoría de los casos), así que solo encuentra esos 5 y colóquelos en su código directamente, no es necesario ir al sitio web de Modernizer, hacer una compilación personalizada, incluirla en su página o lo que sea. Los desarrolladores no deberían ser tan flojos. Un desarrollador web siempre debe tener la mentalidad de "¿cómo puedo hacer que el código sea más ligero?". En mi humilde opinión y años de experiencia. Parece que a los desarrolladores de hoy en día les encanta incluir toneladas de scripts: /
vsync
2
Algunos dicen perezoso. Yo digo ¿por qué reinventar la rueda? ¿Qué pasa cuando aparece un nuevo dispositivo / versión / plataforma y su caso especial necesita ser cambiado? ¿A) Intenta resolver el código de detección de casos especiales por su cuenta y retrocede a su código personalizado, volviendo a familiarizarse con él en el proceso, o b) descarga una versión más reciente de Modernizr y lo deja caer? Sé lo que haría. +1 a GarciaWebDev.
Sc0ttyD
@ Sc0ttyD Mi preferencia personal es aprender a codificar cosas inicialmente sin depender de bibliotecas como Modernizr. Algún día es posible que necesite ser esa persona que codifica el nuevo dispositivo y no quiere quedarse atascado porque no puede hacerlo sin una biblioteca. Sin mencionar que probablemente hay muchas personas que simplemente no tienen el tiempo en su trabajo para aprender una nueva biblioteca.
Alex W
28

En 2017, la consulta de medios CSS de la segunda respuesta todavía no funciona en Firefox. Encontré una solución para eso: -moz-touch-enabled


Entonces, aquí hay una consulta multimedia entre navegadores:

@media (-moz-touch-enabled: 1), (pointer:coarse) {
    .something {
        its: working;
    }
}
Sokołow
fuente
esto debería estar más arriba y la respuesta aprobada. Firefox está trabajando en la implementación de la especificación, por -moz-touch-enabledlo que no será necesario pronto
Dogoku
@ user3445853 OP pregunta cómo detectar (mediante una consulta de medios) el dispositivo con una pantalla táctil. Si la regla "(puntero: ninguno)" es verdadera, entonces el dispositivo no tiene una pantalla táctil con seguridad. Pero alguien debería confirmar mi opinión (o no) :)
Sokołow
-moz-touch-enabledsupuestamente no es compatible con Firefox 58+. Como en, esta solución no cubre Firefox 58-63 (ya que Firefox 64+ admite la consulta de puntero). Fuente: developer.mozilla.org/en-US/docs/Web/CSS/@media/…
fgblomqvist
24

En realidad, hay una consulta de medios para eso:

@media (hover: none) {  }

Además de Firefox, está bastante bien soportado . Safari y Chrome son los navegadores más comunes en dispositivos móviles, puede ser suficiente hasta una mayor adopción.

Buzut
fuente
2
... y apoyo en las próximas semanas para FF también.
retrovertigo
5

Esto funcionará Si no me avisas

@media (hover: none) and (pointer: coarse) {
    /* Touch screen device style goes here */
}

editar: suspender a pedido ya no es compatible

aleksa_95
fuente
3

Esta solución funcionará hasta que CSS4 sea compatible globalmente con todos los navegadores. Cuando llegue ese día solo usa CSS4. pero hasta entonces, esto funciona para los navegadores actuales.

browser-util.js

export const isMobile = {
  android: () => navigator.userAgent.match(/Android/i),
  blackberry: () => navigator.userAgent.match(/BlackBerry/i),
  ios: () => navigator.userAgent.match(/iPhone|iPad|iPod/i),
  opera: () => navigator.userAgent.match(/Opera Mini/i),
  windows: () => navigator.userAgent.match(/IEMobile/i),
  any: () => (isMobile.android() || isMobile.blackberry() || 
  isMobile.ios() || isMobile.opera() || isMobile.windows())
};

onload:

vieja forma:

isMobile.any() ? document.getElementsByTagName("body")[0].className += 'is-touch' : null;

nueva forma:

isMobile.any() ? document.body.classList.add('is-touch') : null;

El código anterior agregará la clase "is-touch" a la etiqueta del cuerpo si el dispositivo tiene una pantalla táctil. Ahora, cualquier ubicación en su aplicación web donde tendría CSS para: pase el mouse al que puede llamarbody:not(.is-touch) the_rest_of_my_css:hover

por ejemplo:

button:hover

se convierte en:

body:not(.is-touch) button:hover

Esta solución evita el uso de modernizer ya que la lib modernizer es una biblioteca muy grande. Si todo lo que intenta hacer es detectar pantallas táctiles, esto será mejor cuando se requiera el tamaño de la fuente compilada final.

Patrick W. McMahon
fuente
0

Agregar una pantalla táctil de clase al cuerpo usando JS o jQuery

  //allowing mobile only css
    var isMobile = ('ontouchstart' in document.documentElement && navigator.userAgent.match(/Mobi/));
    if(isMobile){
        jQuery("body").attr("class",'touchscreen');
    }
Matoeil
fuente
0

Pude resolver este problema usando esto

@media (hover:none), (hover:on-demand) { 
Your class or ID{
attributes
}    
}
Robin Mehdee
fuente
Para su información, on-demandse ha eliminado de la especificación y de los navegadores: github.com/w3c/csswg-drafts/commit/…
retrovertigo