DEV Community

Cover image for Animación de máscaras CSS.
Alfredo Moscoso
Alfredo Moscoso

Posted on • Updated on

Animación de máscaras CSS.

Hoy aprenderemos a animar máscaras css, apoyándonos en la posición del cursor para crear un efecto único para tu próximo proyecto web.

Imagen de una mujer

Demo
https://css-mask-effect.netlify.app/

Github
https://github.com/JairDev/css-mask-effect


El enmascaramiento en css, nos permite “cortar” (enmascarar ) un elemento, ya sea a través de una imagen, un svg o un degradado pudiendo establecer que parte serán o no visibles de ese elemento de acuerdo a la transparencia en la imagen, svg o degradado.

Como podemos ver en este ejemplo, nuestra imagen que servirá de máscara es el logo de apple, es totalmente negra con un fondo transparente y nuestro elemento a enmascarar tiene un fondo de color rosa.

tres imágenes

*La imagen se aplica como máscara al elemento rosa, lo ilustré de esta manera para ver como actúa el fondo transparente de la imagen, solo serían dos elementos, mas adelante lo veremos.


Máscara aplicada

imagen de manzana sobre imagen

La parte mas oscura de nuestra imagen, svg o degradado hacen visible el elemento mientras que la parte mas trasparente ocultan el elemento.

gif de asombro

Propiedad css mask:

La propiedad css mask es un shorthand para mask-image, mask-repeat, mask-position entre otras propiedades, https://developer.mozilla.org/es/docs/Web/CSS/mask.

.element {
  mask-image: url("image-link");
  mask-repeat: no-repeat;
  mask-position: center;
  ...
}
Enter fullscreen mode Exit fullscreen mode

Funciona parecido a la propiedad background de css, podemos establecer una imagen mediante una url, si queremos que se repita o no la máscara, de esta manera tenemos mas control sobre los efectos de nuestra máscara.


Ahora a ensuciarnos las manos ... 😎

Para nuestro efecto vamos a duplicar nuestro elemento .hero.

capas duplicadas

<div class="container">
 <div class="hero">
  <div class="contain-name">
    <h1>Hi, I am Kim,</h1>
    <span>I am a</span>
    <span>web developer.</span>
  </div>
  ...
 </div>

 <div class="hero copy" aria-hidden="true">
  <div class="contain-name">
    <p>Hi, I am Kim,</p>
    <span>I am a</span>
    <span class="span web-developer">web developer.</span>
  </div>
  ...
 </div>
</container

Enter fullscreen mode Exit fullscreen mode

Para mejorar la accesibilidad de nuestro contenido, hemos establecido el elemento duplicado en aria-hidden="true" para evitar que sea mencionado dos veces por lectores de pantalla.

Enmascaramiento del elemento duplicado.

.hero.copy {
 --mask: radial-gradient(
    circle at 15% 50%,
    black 25%,
    transparent 0%
  );
  -webkit-mask: var(--mask);
  mask: var(--mask);
}
Enter fullscreen mode Exit fullscreen mode

Estilos


.container {
  background: #18191c;
}

.hero {
  opacity: 0.6;
}

.hero.copy {
  background: #7f8189af;
  filter: brightness(1.5);
  opacity: 1;
}

.span.web-developer {
  color: #ff03a0;
}
Enter fullscreen mode Exit fullscreen mode

En el elemento .container utilizamos un fondo oscuro y en nuestro elemento base .hero establecemos una opacidad de 0.6 para dar una sensación de oscuridad.

Para la máscara utilizaremos un radial gradient, estableciendo el circulo que vemos a continuación, el fondo será de un color grisáceo para dar el efecto de un foco de luz blanca, aumentaremos un poco el brillo y resaltaremos el texto web developer con un color intenso.

Image description

Como puedes ver, la máscara que es un circulo se está aplicando a nuestro elemento, vamos a difuminar un poco el circulo asignando un 4% al inicio del gradiente y un 25% al final.

.hero.copy {
 --mask: radial-gradient(
    circle at 15% 50%,
    black 4%,
    transparent 25%
  );
  -webkit-mask: var(--mask);
  mask: var(--mask);
}
Enter fullscreen mode Exit fullscreen mode

El resultado ...

Image description

Rastrear la posición del cursor

Para lograr nuestro efecto de "movimiento de la luz", necesitamos rastrear el cursor de acuerdo al movimiento del usuario, JavaScript al rescate 💪

Primero definamos unas propiedades personalizadas "--x", "--y", y establezcamos una posición inicial para la máscara, 15% y 50% respectivamente.

--mask: radial-gradient(
  circle at var(--x, 15%) var(--y, 50%),
  black 4%,
  transparent 25%
  )
Enter fullscreen mode Exit fullscreen mode

En nuestro archivo JS llamamos al evento "mousemove", obtenemos la posición del mouse y hacemos el cálculo para luego asignar ese valor porcentual a nuestras propiedades personalizadas --x y --y.

const hero = document.querySelector(".hero.copy");

window.addEventListener("mousemove", (e) => {
  const x = Math.round((e.clientX / window.innerWidth) * 100);
  const y = Math.round((e.clientY / window.innerHeight) * 100);
  hero.style.setProperty("--x", `${x}%` )
  hero.style.setProperty("--y", `${y}%`)
}); 
Enter fullscreen mode Exit fullscreen mode

Al movimiento de nuestro "foco de luz" le falta un poco de suavidad para que no se sienta tenso. Para lograr esto utilizaré una biblioteca js de animaciones llamada gsap https://greensock.com/docs/, esta biblioteca nos permite establecer una transición de manera sencilla a nuestra máscara ya que estamos utilizando propiedades personalizadas.

npm install gsap

import gsap from "gsap";

const hero = document.querySelector(".hero.copy");

window.addEventListener("mousemove", (e) => {
  const x = Math.round((e.clientX / window.innerWidth) * 100);
  const y = Math.round((e.clientY / window.innerHeight) * 100);
  gsap.to(hero, {
    "--x": `${x}%`,
    "--y": `${y}%`,
    duration: 0.4,
    ease: "sine.out",
  });
});
Enter fullscreen mode Exit fullscreen mode

Ahora nuestro movimiento se siente mas natural 😁

¡Espero este post haya sido de tu agrado!

Te invito a que juegues con las máscaras css y me enseñes ese próximo proyecto donde incluyas grandiosos efectos con esta propiedad.

Tu feedback es de mucha ayuda para mi 🙏

Conectemos 😎
https://twitter.com/JairDevep
https://www.linkedin.com/in/alfredo-moscoso-desarrollador-frontend/

¡Nos vemos pronto! 👊

Top comments (3)

Collapse
 
leviarista profile image
Leví Arista

Interesante! Buen artículo Alfredo.

Collapse
 
jairdev profile image
Alfredo Moscoso

Hola Leví gracias por tu comentario, si, es interesante las cosas que se pueden hacer con css y un poco de JavaScript, haz utilizado las máscaras de css para algún proyecto ?

Collapse
 
leviarista profile image
Leví Arista

Bastante interesante, aún no pero con esto quizás pueda aplicar algunas ideas, así que gracias por el artículo!