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)

16 de julio 2016

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 a cada caso concreto.

Publicado por Jesús Tovar

Categorías: CSS, Diseño, HTML

Etiquetas: , , ,

8 comentarios

  1. leitzaran dice:

    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.

    • Jesús Tovar dice:

      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.

      • leitzaran dice:

        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.

      • leitzaran dice:

        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.

      • Jesús Tovar dice:

        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.

      • leitzaran dice:

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

  2. john dice:

    ¿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ú!!

    • Jesús Tovar dice:

      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.

Pingback

Deja una respuesta

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