Fantástico efecto de cursor para tu avatar | trucos CSS

¿Conoces ese tipo de efecto en el que la cabeza de alguien se asoma a través de un círculo o un agujero? La famosa animación de Porky Pig en la que se despide mientras sale de una serie de anillos rojos es el ejemplo perfecto, y Kilian Valkhoff la recreó aquí en CSS-Tricks hace un tiempo.

Tengo una idea similar pero la hice diferente y con algo de animación. Creo que es bastante práctico y crea un elegante efecto de desplazamiento que puedes usar en algo como tu propio avatar.

¿Ves esto? Vamos a hacer una animación de zoom en la que el avatar parece salirse del círculo en el que se encuentra. Genial, ¿verdad? No mires el código y construyamos juntos esta animación paso a paso.

HTML: solo un elemento

Si no ha revisado el código de demostración y se pregunta cuánto divesto tomará, luego deténgase aquí porque nuestro marcado no es más que un elemento de imagen único:

<img src="" alt="">

¡Sí, un artículo! La parte desafiante de este ejercicio es usar la menor cantidad de código posible. Si me has estado siguiendo por un tiempo, deberías estar acostumbrado a esto. Estoy tratando de encontrar soluciones CSS que se puedan lograr con el código más pequeño y fácil de mantener posible.

He escrito una serie de artículos aquí sobre CSS-Tricks donde exploro diferentes efectos de desplazamiento utilizando el mismo marcado HTML que contiene un solo elemento. Entro en detalles sobre gradientes, máscaras, recortes, contornos e incluso técnicas de diseño. Recomiendo encarecidamente echarles un vistazo porque usaré muchos de los trucos en esta publicación.

Un archivo de imagen que sea cuadrado con un fondo transparente funcionará mejor para lo que estamos haciendo. Aquí está el que uso si quieres empezar con él.

Diseñada por Cang

Espero ver tantos ejemplos de esto como sea posible usando imágenes reales, así que cuando termines, comparte tu resultado final en los comentarios para que podamos crear una colección.

Antes de pasar a CSS, analicemos primero el efecto. La imagen se hace más grande en espera, por lo que seguramente la usaremos transform: scale() adentro. Hay un círculo detrás del avatar y un degradado radial debería funcionar. Finalmente, necesitamos una forma de crear un borde en la parte inferior del círculo que cree la apariencia del avatar detrás del círculo.

¡Pongámonos a trabajar!

El efecto de escala

Comencemos agregando la transformación:

img {
  width: 280px;
  aspect-ratio: 1;
  cursor: pointer;
  transition: .5s;
}
img:hover {
  transform: scale(1.35);
}

Todavía nada complicado, ¿verdad? Continuemos.

El círculo

Dijimos que el fondo sería un degradado radial. Esto es ideal porque podemos crear límites rígidos entre los colores degradados radiales, haciendo que parezca que estamos dibujando un círculo con líneas sólidas.

img {
  --b: 5px; /* border width */

  width: 280px;
  aspect-ratio: 1;
  background:
    radial-gradient(
      circle closest-side,
      #ECD078 calc(99% - var(--b)),
      #C02942 calc(100% - var(--b)) 99%,
      #0000
    );
  cursor: pointer;
  transition: .5s;
}
img:hover {
  transform: scale(1.35);
}

Tenga en cuenta la variable CSS, --bYo uso allí. Representa el grosor del "borde", que en realidad solo se usa para definir los límites de color duros para la parte roja del degradado radial.

El siguiente paso es jugar con el tamaño del degradado en espera. El círculo debe mantener su tamaño a medida que crece la imagen. Ya que aplicamos scale() transformación que realmente necesitamos reducción el tamaño del círculo porque de lo contrario aumenta con el avatar. Entonces, a medida que la imagen se amplía, necesitamos que el degradado se reduzca.

Artículo Recomendado:  Identidad Netlify Trucos CSS para autenticar Jamstack

Comencemos definiendo una variable CSS, --fque define el "factor de escala" y lo usa para establecer el tamaño del círculo. yo suelo 1 como valor predeterminado, ya que esta es la escala inicial de la imagen y el círculo desde el que nos estamos transformando.

Aquí hay una demostración para ilustrar el truco. Pase el cursor para ver lo que sucede detrás de escena:

Agregué un tercer color al radial-gradient Para identificar mejor el área de degradado al pasar el mouse:

radial-gradient(
  circle closest-side,
  #ECD078 calc(99% - var(--b)),
  #C02942 calc(100% - var(--b)) 99%,
  lightblue
);

Ahora debemos colocar nuestro fondo en el centro del círculo y asegurarnos de que ocupe toda la altura. Me gusta declarar todo directamente a background abreviatura para que podamos agregar nuestro posicionamiento de fondo y asegurarnos de que no se repita poniendo estos valores justo después radial-gradient():

background: radial-gradient() 50% / calc(100% / var(--f)) 100% no-repeat;

El fondo está centrado (50%), tiene un ancho igual a calc(100%/var(--f))y tiene una altura igual a 100%.

Nada escala cuando --f es igual a 1 — nuestra escala original de nuevo. Mientras tanto, el degradado ocupa todo el ancho del contenedor. Cuando hacemos zoom --fel tamaño del elemento crece, gracias a scale() transform — y el tamaño del gradiente disminuye.

Esto es lo que obtenemos cuando aplicamos todo esto a nuestra demostración:

¡Nos estamos acercando! Tenemos el efecto de desbordamiento en la parte superior, pero aún necesitamos ocultar la parte inferior de la imagen para que parezca que está saliendo del círculo en lugar de sentarse frente a ella. Esa es la parte complicada de todo esto, y es lo que haremos a continuación.

El límite inferior

Primero traté de lidiar con esto con border-bottom propiedad, pero no pude encontrar una manera de hacer coincidir el tamaño del marco con el tamaño del círculo. Esto es lo mejor que pude obtener, y puede ver de inmediato que está mal:

La solución real es usar outline propiedad Sí, outlineNo border.En un artículo anterior muestro cómo outline es potente y nos permite crear grandes efectos de fijación outline-offsettenemos exactamente lo que necesitamos para nuestro efecto.

La idea es establecer outline en la imagen y ajuste su compensación para crear el borde inferior. La compensación dependerá del factor de escala de la misma manera que el tamaño del degradado.

Ahora tenemos nuestro "límite" inferior (en realidad un outline) combinado con el "borde" creado por el degradado para crear un círculo completo. Todavía tenemos que ocultar partes de outline (superior y lateral), al que llegaremos en un momento.

Aquí está nuestro código hasta ahora, incluidas algunas variables CSS más que puede usar para configurar el tamaño de la imagen (--s) y el color del "marco" (--c):

img {
  --s: 280px; /* image size */
  --b: 5px; /* border thickness */
  --c: #C02942; /* border color */
  --f: 1; /* initial scale */

  width: var(--s);
  aspect-ratio: 1;
  cursor: pointer;
  border-radius: 0 0 999px 999px;
  outline: var(--b) solid var(--c);
  outline-offset: calc((1 / var(--f) - 1) * var(--s) / 2 - var(--b));
  background: 
    radial-gradient(
      circle closest-side,
      #ECD078 calc(99% - var(--b)),
      var(--c) calc(100% - var(--b)) 99%,
      #0000
    ) 50% / calc(100% / var(--f)) 100% no-repeat;
  transform: scale(var(--f));
  transition: .5s;
}
img:hover {
  --f: 1.35; /* hover scale */
}

Como necesitamos un límite inferior circular, agregamos un border-radius en la parte inferior, lo que permite outline para que coincida con la curvatura del gradiente.

Artículo Recomendado:  Línea de tiempo CSS de vista previa de movimiento trucos CSS

El cálculo utilizado en outline-offset es mucho más claro de lo que parece. Por defecto, outline es dibujado afuera de la caja del artículo. Y en nuestro caso lo necesitamos superposición Más precisamente, debería seguir el círculo creado por el degradado.

Diagrama de transición de fondo.

Cuando escalamos el elemento, vemos el espacio entre el círculo y el borde. Recordemos que la idea es mantener el círculo del mismo tamaño después de realizar la transformación de escala, lo que nos deja el espacio que usaremos para definir el desplazamiento del contorno, como se muestra en la figura de arriba.

No olvidemos que el segundo elemento está escalado, por lo que nuestro resultado también está escalado... lo que significa que tenemos que dividir el resultado por f para obtener el valor real de la compensación:

Offset = ((f - 1) * S/2) / f = (1 - 1/f) * S/2

Agregamos un signo negativo porque necesitamos que el contorno vaya de afuera hacia adentro:

Offset = (1/f - 1) * S/2

Aquí hay una demostración rápida que muestra cómo el contorno sigue el degradado:

Probablemente ya pueda verlo, pero aún necesitamos que el contorno inferior se superponga al círculo en lugar de dejar que se desangre. Podemos hacer esto eliminando el tamaño del marco del desplazamiento:

outline-offset: calc((1 / var(--f) - 1) * var(--s) / 2) - var(--b));

Ahora tenemos que averiguar cómo eliminar la parte superior del contorno. En otras palabras, solo queremos la parte inferior de la imagen. outline.

Primero, agreguemos algo de espacio en la parte superior con relleno para evitar la superposición en la parte superior:

img {
  --s: 280px; /* image size */
  --b: 5px;   /* border thickness */
  --c: #C02942; /* border color */
  --f: 1; /* initial scale */

  width: var(--s);
  aspect-ratio: 1;
  padding-block-start: calc(var(--s)/5);
  /* etc. */
}
img:hover {
  --f: 1.35; /* hover scale */
}

No hay una lógica particular en este pad superior. La idea es asegurarse de que el contorno no toque la cabeza del avatar. Usé el tamaño del elemento para definir este espacio para que siempre tenga la misma relación de aspecto.

Tenga en cuenta que agregué content-box valor por background:

background:
  radial-gradient(
    circle closest-side,
    #ECD078 calc(99% - var(--b)),
    var(--c) calc(100% - var(--b)) 99%,
    #0000
  ) 50%/calc(100%/var(--f)) 100% no-repeat content-box;

Necesitamos esto porque agregamos un pad y solo queremos que el fondo se establezca en el cuadro de contenido, por lo que debemos decirle explícitamente al fondo que se detenga allí.

Agregar una máscara CSS a la mezcla

¡Hemos llegado a la última parte! Todo lo que tenemos que hacer es esconder algunas piezas y listo. Para ello nos apoyaremos mask propiedad y por supuesto gradientes.

Aquí hay una figura que ilustra lo que debemos ocultar o lo que debemos mostrar para ser más precisos.

Muestra cómo se aplica la máscara en la parte inferior del círculo.

La imagen de la izquierda es lo que tenemos actualmente y la derecha es lo que queremos.La parte verde ilustra la máscara que debemos aplicar a la imagen original para obtener el resultado final.

podemos identificar dos partes de nuestra máscara:

  • Un círculo en la parte inferior que tiene las mismas dimensiones y curvatura que el degradado radial que usamos para crear el círculo detrás del avatar.
  • Un rectángulo en la parte superior que cubre el área dentro del contorno. Observe cómo el contorno está fuera del área verde en la parte superior: esta es la parte más importante, ya que permite recortar el contorno para que solo se vea la parte inferior.
Artículo Recomendado:  ¡CSS-Tricks se une a DigitalOcean! | Trucos CSS

Aquí está nuestro CSS final:

img {
  --s: 280px; /* image size */
  --b: 5px; /* border thickness */
  --c: #C02942; /* border color */
  --f: 1; /* initial scale */

  --_g: 50% / calc(100% / var(--f)) 100% no-repeat content-box;
  --_o: calc((1 / var(--f) - 1) * var(--s) / 2 - var(--b));

  width: var(--s);
  aspect-ratio: 1;
  padding-top: calc(var(--s)/5);
  cursor: pointer;
  border-radius: 0 0 999px 999px;
  outline: var(--b) solid var(--c);
  outline-offset: var(--_o);
  background: 
    radial-gradient(
      circle closest-side,
      #ECD078 calc(99% - var(--b)),
      var(--c) calc(100% - var(--b)) 99%,
      #0000) var(--_g);
  mask:
    linear-gradient(#000 0 0) no-repeat
    50% calc(-1 * var(--_o)) / calc(100% / var(--f) - 2 * var(--b)) 50%,
    radial-gradient(
      circle closest-side,
      #000 99%,
      #0000) var(--_g);
  transform: scale(var(--f));
  transition: .5s;
}
img:hover {
  --f: 1.35; /* hover scale */
}

Vamos a desglosar esto mask Para empezar, observe que una similar radial-gradient() de background la propiedad está allí. Creé una nueva variable, --_gpara las zonas comunes para que sea menos desordenado.

--_g: 50% / calc(100% / var(--f)) 100% no-repeat content-box;

mask:
  radial-gradient(
    circle closest-side,
    #000 99%,
    #0000) var(--_g);

Entonces hay un linear-gradient() y ahí:

--_g: 50% / calc(100% / var(--f)) 100% no-repeat content-box;

mask:
  linear-gradient(#000 0 0) no-repeat
    50% calc(-1 * var(--_o)) / calc(100% / var(--f) - 2 * var(--b)) 50%,
  radial-gradient(
    circle closest-side,
    #000 99%,
    #0000) var(--_g);

Esto crea la parte rectangular de la máscara, su ancho es igual al ancho del degradado radial menos el doble del grosor del borde:

calc(100% / var(--f) - 2 * var(--b))

La altura del rectángulo es igual a la mitad, 50%del tamaño del elemento.

También necesitamos el gradiente lineal colocado en el centro horizontal (50%) y desplazado desde arriba por el mismo valor que el desplazamiento del contorno. Creé otra variable CSS, --_opara el desplazamiento que definimos anteriormente:

--_o: calc((1 / var(--f) - 1) * var(--s) / 2 - var(--b));

Una de las cosas confusas aquí es que necesitamos la negativo desplazamiento para el contorno (para moverlo de afuera hacia adentro), pero un positivo compensación para el degradado (para moverse de arriba a abajo). Entonces, si se pregunta por qué estamos multiplicando la compensación, --_ode -1¡bien ahora lo sabes!

Aquí hay una demostración para ilustrar la configuración de la máscara de degradado:

Pase el cursor sobre lo anterior y vea cómo se mueve todo junto. El cuadro central ilustra una máscara de capa compuesta por dos degradados. ¡Piense en ello como la parte visible de la imagen de la izquierda y obtendrá el resultado final a la derecha!

resumiendo

¡Uf, hemos terminado! Y no solo terminamos con una elegante animación flotante, sino que lo hicimos todo con un solo HTML <img> elemento. ¡Solo eso y menos de 20 líneas de trucos CSS!

Por supuesto, nos basamos en algunos pequeños trucos y fórmulas matemáticas para lograr un efecto tan complejo. Pero sabíamos exactamente qué hacer porque habíamos identificado las piezas que necesitábamos con anticipación.

¿Podríamos simplificar CSS si nos permitiéramos más HTML? Absolutamente. ¡Pero estamos aquí para aprender nuevos trucos de CSS! Este fue un buen ejercicio para explorar gradientes CSS, enmascaramiento, outline comportamiento de propiedades, transformaciones y mucho más. Si te has sentido perdido en algún momento, definitivamente echa un vistazo a mi serie que utiliza los mismos conceptos generales. A veces, es útil ver más ejemplos y casos de uso para llevar un punto a casa.

Los dejaré con una demostración final que utiliza imágenes de desarrolladores populares de CSS. ¡Asegúrate de mostrarme una demostración de tu propia imagen para que pueda agregarla a la colección!

Deja una respuesta

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

Subir

https://kirin-mountainview.com/

https://www.bamboo-thai.com/