Detectar si un dispositivo cliente es compatible con: hover y: estados de enfoque

Suena como un problema simple, pero resulta bastante difícil de resolver. Para algunos sitios web, tengo contenidos que solo se mostrarán si un usuario desplaza / enfoca un enlace. El enlace sin embargo tiene un objective en sí mismo.

Si un usuario de la pantalla táctil hace clic en uno de esos enlaces, el navegador irá instantáneamente a la ubicación href . Esto significa que los contenidos de la hover nunca son visibles!

Es por esto que los usuarios que no tienen un mouse (u otro dispositivo para desplazarse como un control remoto mágico) deben ver contenido alternativo. Pero, ¿cómo puedo detectar esto?

 $(document).on('click','#my-menu-inner > ul > li > a',function(e) { if(clientHasInputDeviceSupportingHover()) { return true; } else { e.preventDefault(); $('#for-no-hover-visitors').html(''); $(this).clone().appendTo('#for-no-hover-visitors'); $(this).next().clone().appendTo('#for-no-hover-visitors'); } }); function clientHasInputDeviceSupportingHover() { // HOW CAN I DETECT THIS??? if($('#checkhover:checked').length > 0) { return true; } return false; } 
 .clearfix::after { content: ""; clear: both; display: table; } #my-menu-inner > ul { margin:10px; width:100%; background-color:yellow; list-style-type:none; position:relative; } #my-menu-inner > ul > li { float:left; margin:20px; } #my-menu-inner > ul > li > a { padding:20px; border:1px solid black; display:block; } #my-menu-inner > ul > li > div.sub { position:absolute; top:calc(100% - 20px); background-color:red; padding:40px; display:none; left:0; width:100vw; } #my-menu-inner > ul > li a:hover + div.sub, #my-menu-inner > ul > li a:focus + div.sub, #my-menu-inner > ul > li > div.sub:hover, #my-menu-inner > ul > li > div.sub:focus { display:block; } 
  Simulate for Client supporting hover:   

El problema es clientHasInputDeviceSupportingHover() . ¿Cuál es la forma más confiable de averiguarlo?

Lo que sabemos hasta ahora

Es posible detectar un dispositivo táctil: ¿Cuál es la mejor manera de detectar un dispositivo de ‘pantalla táctil’ utilizando JavaScript?

La detección del mouse al menos podría funcionar “onclick”: ¿Cómo detectar si un dispositivo tiene soporte para mouse?

En general, hay muchos dispositivos de entrada posibles diferentes: https://en.wikipedia.org/wiki/Input_device#Pointing_device

Una solución genérica / más confiable sería muy bienvenida.

Un enfoque, si puede usar CSS actualizado (y consultar la tabla de compatibilidad en los recursos vinculados):

 /* Here we use media queries to test the device's support for the 'pointer' property, here we check if the 'fine' property-value is supported by the device: */ @media (pointer:fine) { /* Here we set variables to use in styling the subsequent content which will identify the pointer support: */ :root { --hasTouch: orangered; } } @media (pointer:coarse) { :root { --hasTouch: limegreen; } } @media (pointer:fine) and (pointer:coarse) { :root { --hasTouch: skyblue; } } /* Note that we don't specify the variable in the event of the device not supporting the 'pointer' property or property-value; therefore if the 
is white (#fff) then we're using the default value from the var() function: */ div { background-color: var(--hasTouch, #fff); height: 5em; border: 2px solid #000; }
 *, ::before, ::after { margin: 0; padding: 0; box-sizing: border-box; } @media (pointer:fine) { :root { --hasTouch: orangered; } } @media (pointer:coarse) { :root { --hasTouch: limegreen; } } @media (pointer:fine) and (pointer:coarse) { :root { --hasTouch: skyblue; } } div { background-color: var(--hasTouch, #fff); height: 5em; border: 2px solid #000; } ul { width: 80vw; margin: 0.5em auto; list-style-type: none; } li::before { content: ''; display: inline-block; width: 1em; height: 1em; background-color: currentColor; border-radius: 50%; border: 2px solid #000; } .failure { color: #000; } .orangered::before { color: orangered; } .limegreen::before { color: limegreen; } .skyblue::before { color: skyblue; } 
 
  • - Doesn't appear to understand pointer.
  • - Probably uses a mouse.
  • - Probably uses touch
  • - Could maybe have both mouse and touch.

El W3C parece haber reconocido este problema y ha introducido la función de desplazamiento:

La función de medios de desplazamiento se usa para consultar la capacidad del usuario para hover sobre los elementos de la página con el dispositivo señalador principal. Si un dispositivo tiene varios dispositivos señaladores, la función de medios de desplazamiento debe reflejar las características del dispositivo señalador “primario”, según lo determine el agente del usuario. (Para consultar las capacidades de cualquier dispositivo señalador disponible, vea la función de medios con cualquier desplazamiento).

Incluso hay una consulta de medios para verificar si existe la posibilidad de desplazarse:

Las características de los medios de comunicación de any-pointer y de any-hover son idénticas a las características de los medios de puntero y de desplazamiento, pero corresponden a la unión de capacidades de todos los dispositivos de señalización disponibles para el usuario. En el caso de cualquier puntero, más de uno de los valores puede coincidir, si diferentes dispositivos apuntadores tienen características diferentes.

Muestras de código:

 /* Primary input mechanism system can hover over elements with ease */ @media (hover: hover) { ... } /* Primary input mechanism cannot hover at all or cannot conveniently hover (eg, many mobile devices emulate hovering when the user performs an inconvenient long tap), or there is no primary pointing input mechanism */ @media (hover: none) { ... } /* One or more available input mechanism(s) can hover over elements with ease */ @media (any-hover: hover) { ... } /* One or more available input mechanism(s) cannot hover (or there are no pointing input mechanisms) */ @media (any-hover: none) { ... } 

Borrador oficial: https://drafts.csswg.org/mediaqueries/#hover

Esta función aún está en riesgo, pero realmente espero que sea totalmente compatible pronto, ya que es ampliamente compatible: https://caniuse.com/#feat=css-media-interaction

Más información: https://css-tricks.com/touch-devices-not-judged-size/

Para Chrome, pruebe su dispositivo aquí: https://googlechrome.github.io/samples/media-hover-pointer/

Prueba con JavaScript: https://jsfiddle.net/Blackbam/zkd2cs0t/16/

La mejor solución por ahora es, probablemente, utilizar esas consultas de medios con una solución alternativa utilizando la detección táctil mediante document.createEvent("TouchEvent"); y la detección del ratón a través de mousemove.hasMouse .