Pseudoclase :hover de CSS no funciona en iOS (iPhone, iPad e iPod)

Pseudo-clase :hover de CSS no funciona en iOS (iPhone, iPad e iPod)

Lo que vamos a ver en este artículo es algo curioso que sucede en ciertos terminales de pantalla táctil al usar la pseudo-clase :hover de CSS en una página web. A mi concretamente me ha ocurrido sólo en dispositivos iOS (iPhone, iPad e iPod), pero imagino que también es susceptible que ocurra en otros.

Había creado un <div> que contenía una lista dentro y que en estado de reposo quedaba oculta, de modo que cuando se pasara el ratón por encima, la lista se desplegase. Esto en ordenadores funcionaba correctamente al hacer rollover y en móviles al hacer click o mejor dicho tocar. Sin embargo, como no tengo ningún dispositivo de Apple no pude comprobarlo en éstos y no es hasta que un cliente me avisó, que pude saber que no funcionaba. La capa en cuestión quedaba siempre cerrada sin posibilidad de ver el interior.

Después de indagar un poco, al parecer la versión móvil de Safari por defecto sólo identifica ciertos elementos como interactivos, eso provoca que si aplicamos esa interactividad a un elemento que típicamente no lo es, el navegador no desencadena el evento al tocarlo. Esos elementos concretos son los siguientes, aunque para algunos es necesario que se cumplan además ciertos requisitos:

<a>
<area>
<button>
<img>
<input>
<label>
<textarea>

Para indicarle al navegador de los dispositivos iOS que queremos poder usar la pseudo-clase :hover en cualquier tipo de etiqueta que tengamos en la web, como un <div>, utilizaremos ontouchstart en el <body>, cuya sintaxis varía dependiendo de la versión que usemos de HTML.

<body ontouchstart> <!-- en HTML5 -->
<body ontouchstart=""> <!-- en HTML -->

Con esto hemos resuelto la mitad del problema, ya que ahora al tocar el <div> se abrirá la capa, pero al retirar el dedo se volverá a cerrar sin darnos posibilidad a pulsar nada dentro. Así que lo que debemos hacer es incluir la pseudo-clase :focus en el mismo estilo que hemos creado para :hover. De este modo conseguimos que al pulsar el foco se encuentre en la capa y por tanto quede abierta hasta que hagamos una interacción.

.capa:hover, .capa:focus{
max-height:250px;
}

El motivo por el cual he dicho añadir :focus en lugar de sustituirlo es porque si bien nos servirá para Safari móvil de iPhone, iPad e iPod, en el ordenador nos obligaría a hacer click en el <div> para desplegarlo. Si dejamos los dos, conseguiremos el efecto adecuado en cada dispositivo sin que haya conflicto.

Aunque me he centrado en :hover, realmente se podría aplicar a otras pseudoclases que requieran interacción con el usuario en elementos que no se encuentren en la lista que comenté al principio. Es cuestión de adaptar la solución como diseñador web a cada caso concreto.

12 respuestas a «Pseudo-clase :hover de CSS no funciona en iOS (iPhone, iPad e iPod)»

  1. Avatar de Carina
    Carina

    Hola Jesús, recientemente me encuentro con este problema, al ver que el sitio web se visualiza bien en todos los dispositivos, excepto en iphone, he colocado ontouchstart en el body, y repliqué todas las etiquetas en las que tenia un : hover, con :focus también.
    La cosa es que cuando cargo la página por primera vez los menúes multilínea se ven bien y aceptan el touch o clic en el móvil, pero al volver hacia atrás ya no funciona el menú multilinea, esto solo sucede en iphone

    1. Avatar de Jesús Tovar

      Hola Carina, ¿cómo vuelves hacia atrás, navegando por el menú de la web o usando el botón de volver del navegador?

    2. Avatar de Carina
      Carina

      Hola Jesús, ya lo pude arreglar, lo que está escrito en este foro funciona correctamente. El inconveniente era que el ontouch del body se lo había agregado al index.html solamente y hay que colocarlo en todas las páginas del sitio.
      Muchas gracias!!!!

    3. Avatar de Jesús Tovar

      Efectivamente Carina, ontouchstart hay que ponerlo en el body de todas las páginas donde quieras aplicarlo. Me alegra que te haya servido. ¡Un saludo!

  2. Avatar de leitzaran
    leitzaran

    Hola, Jesús:
    El atributo ontouchstart ¿tiene que ir colocado necesariamente en body? ¿o puede ir en un div que a su vez contenga los elementos en los que se va a hacer hover (normalmente menús)?
    Gracias por tu respuesta.

    1. Avatar de Jesús Tovar

      Hola, el atributo ontouchstart puede ir en cualquier elemento HTML para indicarle a Safari Mobile que debe habilitar su interactividad. Si lo haces en el body se activará en todos los que compongan la página.

    2. Avatar de leitzaran
      leitzaran

      Gracias.
      Mi interés en no hacerlo en body es porque tendría que modificar todas las páginas, mientras que la sección de cabecera (donde están los menús) la cargo con un include, y sólo tengo que modificar un archivo.
      Ya he añadido tus sugerencias (ontouchstart y :focus), a ver si hoy mismo puedo probarlo en un iphone real.
      Gracias de nuevo por tus aportaciones.

    3. Avatar de leitzaran
      leitzaran

      Hola de nuevo,
      Probado, con éxito.
      Sólo queda un fleco: Si desplegamos el menú (en cualquiera de sus dos niveles), al clicar en algún lugar libre de la pantalla debería replegarse, y no lo hace. ¿Alguna sugerencia?
      Gracias.

    4. Avatar de Jesús Tovar

      Esto que comentas de que el menú no se cierra al hacer click fuera, te diré que es normal en tu caso. Me explico:

      Estamos usando pseudo-clases de CSS para conseguir el efecto de apertura y cierre. Cuando utilizamos el ratón nos valemos de :hover y todo depende de si el cursor pasa por encima del área de acción, es simple. Sin embargo al incluir :focus para los móviles la cosa cambia, ya que no basta con salir del área de acción, debemos pasar el foco a otro elemento. Al hacer que solo sea interactivo el div de tu menú, el resto de elementos que nos son propiamente interactivos no podrán recibir el foco y no cambiará el estado a reposo, que es el que hará que se cierre. No sé si me he explicado bien.

      En este punto lo más sencillo de implementar sería pasar ontouchstart al body, quizá usando un macro tipo «buscar y reemplazar» si tienes demasiadas páginas. Ahora mismo sin usar JavaScript no se me ocurre ninguna alternativa eficiente. Eso sí, te recomiendo que hagas una prueba con una sola página antes, no sea que en los navegadores más reciente haya cambiado algo.

    5. Avatar de leitzaran
      leitzaran

      Ahora entiendo por qué ponerlo en body. A por ello.

  3. Avatar de john
    john

    ¿Te ha ocurrido alguna vez que la barra de menú funcione perfecta en Pc pero en dispositivos móviles al desplegar el menú y clickar en un submenu se recoja sola la barra sin hacer nada?, lo raro es que si una categoría no tiene subcategoria si clickas te redirecciona pero si esta misma tiene subcategoria al clickar en alguna de ella solo se recoge el menú!!

    1. Avatar de Jesús Tovar

      Hola John,

      Si hablamos de un menú que no usa JavaScript, esto que comentas suele deberse a motivos relacionados con jerarquía de elementos y las áreas sensibles que contienen los enlaces. Es decir, que normalmente hay un problema en el orden de las pseudo-clases que se aplican a los estados.

      Cuando un elemento del menú no tiene hijos, es decir, no tiene anidado un submenú se comporta como un enlace simple, haces click y te lleva donde corresponda. Sin embargo cuando es un elemento padre, que sirve para mostrar otros elementos que son dependientes, se puede producir un conflicto si no hemos definido bien las clases en CSS al encontrarse un enlace en el mismo lugar que el área sensible para mostrar ese submenú. Mientras en el PC los eventos de ratón click y over son diferentes y por tanto podemos diferenciar entre pasar el cursor por encima y pulsar, en los smartphones y tablets básicamente se fusionan debido al propio hardware ya que con el dedo solo se puede tocar.

      Prueba a revisar dónde has ubicado el evento :hover para asegurarte que está en el lugar correcto.

      Un saludo.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *