Advertisement
  1. Web Design
  2. Navigation Design

¿Cómo hacer un Efecto Hover de Subrayado Movedizo con CSS y JavaScript?

by
Read Time:6 minsLanguages:

Spanish (Español) translation by Cristian Marroquin (you can also view the original English article)

En el tutorial de Hoy, vamos a usar un poco de CSS y JavaScript para crear un sofisticado menu con efecto hover. No es un resultado final complicado, pero construirlo sera una gran oportunidad para practicar nuestras habilidades de front-end.

Sin mas introducción, veamos lo que estaremos creando:

El Marcado

Empezamos con un un marcado básico; un elemento nav el cual contiene el menú y un elemento span vacío.

El CSS

Con el marcado listo, a continuación especificamos algunos estilos basicos para los elementos relacionados:

Nota que el elemento span (.target) esta posicionado de manera absoluta. Como veremos en un momento, usaremos JavaScript para determinar su posición exacta. Ademas, debe aparecer detrás de los enlaces del menú, para ello le damos un z-index negativo.

El JavaScript

En este punto, enfocaremos nuestra atención en el JavaScript. para empezar, obtenemos los elementos deseados. También definimos un arreglo de colores que usaremos después.

Eventos

A continuación escuchamos los eventos click y mouseenter de los enlaces del menú.

Cuando el evento click ocurre, evitamos que la pagina se vuelva a cargar. por supuesto, esto funciona en nuestro caso por que todos los enlaces tiene un atributo href vació. En un proyecto real sin embargo, cada enlace del menú probablemente abrirá una pagina diferente.

Mas importante aun, tan pronto como el evento mouseenter se dispara, la función de llamada de retorno mouseenterFunc es ejecutada:

mouseenterFunc

El cuerpo de la función mouseenterFunc se ve como esto:

Dentro de esta función hacemos lo siguiente:

  1. Agregar la clase active al padre inmediato (li) del enlace objetivo.
  2. Reducir la propiedad opacity de todos los enlaces del menu, excepto para el "activo".
  3. Usar el método getBoundingClientRect para recuperar el tamaño del enlace asociado y su posición relativa a la vista.
  4. Obtener un color aleatorio del arreglo antes mencionado y pasarlo como valor a la propiedad border-color del elementospan. Recuerda, la propiedad inicial esta establecida en transparent.
  5. Asignar el valor extraído del método getBoundingClientRect a las propiedades correspondientes del elemento span. En otras palabras, la etiqueta span hereda el tamaño y la posición del enlace que tiene al puntero encima.
  6. Restablecer la transformación aplicada al elemento span. Este comportamiento es solamente importante la primera vez que se ubica el puntero encima de un enlace. En este caso, la transformación del elemento va de transform: translateX(-60px) a transform: none que nos da un bonito efecto de deslizamiento.

Si está activado

Es importante notar que el código anterior se ejecuta cada vez que pasamos el puntero sobre un enlace, por lo tanto también se ejecuta cuando pasamos el puntero sobre un enlace "activo". Para prevenir este comportamiento, rodearemos el código con una sentencia if:

En este punto, nuestro ejemplo se parece a lo siguiente:

Casi, pero No Tanto

Bien, todo parece funcionar como se esperaba, ¿cierto? Pues, no es cierto porque si nos desplazamos a través de la página, o cambiamos el tamaño de la ventana y luego tratamos de seleccionar un enlace, las cosas se desordenan. Específicamente, la posición del elemento span se vuelve incorrecta.

Prueba el ejemplo en pagina completa para ver lo que quiero decir.

Para Resolver esto, tenemos que calcular cuanto nos hemos desplazado del la parte superior de la ventana y sumar este valor con el valor actual de top del elemento objetivo. Del mismo modo debemos calcular cuanto se ha desplazado el documento horizontalmente (por si acaso). El valor resultante es sumado con el valor actual de left del elemento objetivo.

Aquí están las dos lineas de código que actualizaremos:

Ten en mente que todo el código anterior es ejecutado tan pronto como el navegador procese el DOM y encuentre el las instrucciones relevante. De nuevo, para tus propias  implementaciones y diseños puedes querer que este código se ejecute cuando la pagina se cargue, o algo parecido. En ese caso, tienes que incrustarlo dentro de un manejador de evento (ej. el manejador de evento load)

Tamaño de la ventana

Lo ultimo que tenemos que hace es asegurar que el efecto va a funcionar aun si cambiamos el tamaño de la ventana del navegador. Para lograr esto, escuchamos el evento resize y registramos el manejador de evento resizeFunc.

Aquí esta el cuerpo de este manejador:

Dentro de la función anterior, haremos lo siguiente:

  1. Verificar si hay un elemento de lista dentro del menú que tenga la clase active. Si hay tal elemento, significa que ya hemos pasado sobre un enlace. 
  2. Obtener las nuevas propiedades left y top del elemento "activo" junto con las propiedades de ventana respectivas y asignarlas al elemento span. Nota que hemos recuperado los valores solo para las propiedades que cambian durante el evento resize. Eso significa, no hay necesidad de recalcular el ancho y alto de los enlaces del menú.

Navegadores Soportados

Este ejemplo funciona bien en todos los navegadores actuales. Sin embargo si encuentras algún problema, házmelo saber en los comentarios en la parte inferior. También como probablemente notaste, usamos Babel para compilar nuestro código de ES6 a ES5.

Conclusión

En este ejemplo rápido pasamos por el proceso de creación de un sencillo, pero interesante menú con efecto hover.

Espero que disfrutaras lo que creamos y te sirva de inspiración para desarrollar efectos de menús mucho mas poderosos como el que aparece (al momento de escribir esto) en el sitio de Stripe.

Alguna vez has creado algo similar? Si es así, asegúrate de compartir con nosotros los desafíos que enfrentaste.

Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.