Tengo algunos menús css en mi sitio que se expanden con :hover
(sin js)
Esto funciona de forma semi-rota en iDevices, por ejemplo, un toque activará la :hover
regla y expandirá el menú, pero luego tocar en otro lugar no elimina el :hover
. Además, si hay un enlace dentro del elemento que está :hover
editado, debe tocar dos veces para activar el enlace (el primer toque desencadena :hover
, el segundo toque desencadena el enlace).
He podido hacer que las cosas funcionen bien en el iPhone vinculando el touchstart
evento.
¡El problema es que a veces el safari móvil todavía elige activar la :hover
regla desde el CSS en lugar de mis touchstart
eventos!
Sé que este es el problema porque cuando desactivo todas las :hover
reglas manualmente en el CSS, el safari móvil funciona muy bien (pero los navegadores normales obviamente ya no lo hacen).
¿Hay alguna forma de "cancelar" dinámicamente las :hover
reglas para ciertos elementos cuando el usuario está en un safari móvil?
Vea y compare el comportamiento de iOS aquí: http://jsfiddle.net/74s35/3/ Nota: que solo algunas propiedades de CSS activan el comportamiento de dos clics, por ejemplo, display: none; pero no fondo: rojo; o decoración de texto: subrayado;
fuente
Respuestas:
Descubrí que ": hover" es impredecible en iPhone / iPad Safari. A veces, toca un elemento para hacer que ese elemento sea ": hover", mientras que a veces se desplaza a otros elementos.
Por el momento, solo tengo una clase de "no tocar" en el cuerpo.
Y tener todas las reglas CSS con ": hover" debajo de ".no-touch":
En algún lugar de la página, tengo javascript para eliminar la clase sin contacto del cuerpo.
Esto no parece perfecto, pero funciona de todos modos.
fuente
:hover
no es el problema aquí. Safari para iOS sigue una regla muy extraña. Disparamouseover
ymousemove
primero; si se cambia algo durante estos eventos, el 'clic' y los eventos relacionados no se disparan:mouseenter
ymouseleave
parecen estar incluidos, aunque no se especifican en el gráfico.Si modifica algo como resultado de estos eventos, los eventos de clic no se activarán. Eso incluye algo más arriba en el árbol DOM. Por ejemplo, esto evitará que los clics individuales funcionen en su sitio web con jQuery:
Editar: para aclarar, el
hover
evento de jQuery incluyemouseenter
ymouseleave
. Ambos evitaránclick
si se cambia el contenido.fuente
hover
controlador jquery estaba evitando queclick
se golpeara a un controlador separado , ¡qué broma!mouseenter
activaLa biblioteca de detección de funciones del navegador Modernizer incluye una verificación de eventos táctiles.
Su comportamiento predeterminado es aplicar clases a su elemento html para cada característica que se detecta. A continuación, puede utilizar estas clases para diseñar su documento.
Si los eventos táctiles no están habilitados, Modernizr puede agregar una clase de
no-touch
:Y luego amplíe sus estilos de desplazamiento con esta clase:
Puede descargar una compilación personalizada de Modernizr para incluir tantas o pocas detecciones de funciones como necesite.
Aquí hay un ejemplo de algunas clases que pueden aplicarse:
fuente
Algunos dispositivos (como han dicho otros) tienen eventos táctiles y de mouse. Microsoft Surface, por ejemplo, tiene una pantalla táctil, un trackpad Y un lápiz que en realidad genera eventos de desplazamiento cuando se coloca sobre la pantalla.
Cualquier solución que se desactive en
:hover
función de la presencia de eventos 'táctiles' también afectará a los usuarios de Surface (y a muchos otros dispositivos similares). Muchas computadoras portátiles nuevas son táctiles y responderán a eventos táctiles, por lo que deshabilitar el desplazamiento es una mala práctica.Este es un error en Safari, no hay absolutamente ninguna justificación para este terrible comportamiento. Me niego a sabotear navegadores que no sean iOS debido a un error en iOS Safari que aparentemente ha estado allí durante años. Realmente espero que solucionen esto para iOS8 la próxima semana, pero mientras tanto ...
Mi solucion :
Algunos ya han sugerido usar Modernizr, bueno, Modernizr le permite crear sus propias pruebas. Básicamente, lo que estoy haciendo aquí es 'abstraer' la idea de un navegador compatible
:hover
con una prueba de Modernizr que puedo usar en todo mi código sin codificación completaif (iOS)
.Entonces el CSS se convierte en algo como esto
Solo en iOS esta prueba fallará y deshabilitará la sustitución.
La mejor parte de tal abstracción es que si encuentro que se rompe en un determinado Android o si está arreglado en iOS9, entonces puedo modificar la prueba.
fuente
html:not(.no-hover) .category:hover { ...
Agregar la biblioteca FastClick a su página hará que todos los toques en un dispositivo móvil se conviertan en eventos de clic (independientemente de dónde haga clic el usuario), por lo que también debería solucionar el problema de desplazamiento en dispositivos móviles. Edité tu violín como ejemplo: http://jsfiddle.net/FvACN/8/ .
Simplemente incluya la lib fastclick.min.js en su página y actívela a través de:
Como beneficio adicional, también eliminará el molesto retraso de 300 ms al hacer clic que sufren los dispositivos móviles.
Hay un par de consecuencias menores al usar FastClick que pueden o no ser importantes para su sitio:
fuente
Una mejor solución, sin ningún tipo de verificación JS, css class y viewport: puede usar Interaction Media Features (Media Queries Level 4)
Me gusta esto:
iOS Safari lo admite
Más sobre: https://www.jonathanfielding.com/an-introduction-to-interaction-media-features/
fuente
Básicamente, hay tres escenarios:
:hover
:hover
elementosLa respuesta aceptada originalmente funciona muy bien si solo son posibles los dos primeros escenarios, donde un usuario tiene un puntero o una pantalla táctil. Esto era común cuando el OP hizo la pregunta hace 4 años. Varios usuarios han señalado que los dispositivos Windows 8 y Surface hacen que el tercer escenario sea más probable.
La solución de iOS al problema de no poder desplazarse en los dispositivos con pantalla táctil (como lo detalla @Zenexer) es inteligente, pero puede hacer que el código sencillo se comporte mal (como lo señaló el OP). Desactivar el desplazamiento solo para dispositivos con pantalla táctil significa que aún deberá codificar una alternativa compatible con la pantalla táctil. Detectar cuándo un usuario tiene tanto el puntero como la pantalla táctil enturbia aún más las aguas (como lo explica @Simon_Weaver).
En este punto, la solución más segura es evitar el uso
:hover
como la única forma en que un usuario puede interactuar con su sitio web. Los efectos de desplazamiento son una buena forma de indicar que un enlace o botón es accionable, pero no se debería exigir al usuario que coloque el cursor sobre un elemento para realizar una acción en su sitio web.Repensar la funcionalidad "hover" con pantallas táctiles en mente tiene una buena discusión sobre enfoques alternativos de UX. Las soluciones proporcionadas por la respuesta allí incluyen:
En el futuro, esta será probablemente la mejor solución para todos los proyectos nuevos. La respuesta aceptada es probablemente la segunda mejor solución, pero asegúrese de tener en cuenta los dispositivos que también tienen dispositivos de puntero. Tenga cuidado de no eliminar la funcionalidad cuando un dispositivo tiene una pantalla táctil solo para evitar el
:hover
hack de iOS .fuente
La versión de JQuery en su .css usa .no-touch .my-element: hover para todas sus reglas de hover incluyen JQuery y el siguiente script
Luego, en la etiqueta del cuerpo, agregue class = "no-touch" ontouchstart = "removeHoverState ()"
tan pronto como ontouchstart se activa, se elimina la clase para todos los estados de desplazamiento
fuente
En lugar de tener solo efectos de desplazamiento cuando el toque no está disponible, creé un sistema para manejar eventos táctiles y eso me ha resuelto el problema. Primero, definí un objeto para probar eventos de "tap" (equivalente a "clic").
Luego, en mi controlador de eventos hago algo como lo siguiente:
fuente
Gracias @Morgan Cheng por la respuesta, sin embargo, modifiqué ligeramente la función JS para obtener el " touchstart " (código tomado de la respuesta de @Timothy Perez ), sin embargo, necesita jQuery 1.7+ para esto
fuente
Dada la respuesta proporcionada por Zenexer, un patrón que no requiere etiquetas HTML adicionales es:
Este método dispara primero el mouseover, luego el clic.
fuente
Estoy de acuerdo en que deshabilitar el desplazamiento del mouse para tocar es el camino a seguir.
Sin embargo, para evitarse la molestia de volver a escribir su css, simplemente envuelva los
:hover
elementos en@supports not (-webkit-overflow-scrolling: touch) {}
fuente
Para aquellos con un caso de uso común de deshabilitar
:hover
eventos en iOS Safari, la forma más sencilla es usar una consulta de medios de ancho mínimo para sus:hover
eventos que permanece por encima del ancho de pantalla de los dispositivos que está evitando. Ejemplo:fuente
Solo mire el tamaño de la pantalla ...
fuente
aquí está el código en el que querrás colocarlo
fuente