Animaciones de bordes CSS

Veamos varias formas de animar un borde en CSS

Configuración de bordes

Hay algunos métodos disponibles para establecer un borde en un elemento: border, outline y box-shadow. Como se detalla en Los 3 métodos CSS para agregar bordes de elementos de Stephanie Eckles, cada enfoque tiene sus propias ventajas y desventajas, en especial cuando se trata de animar los bordes. El motivo principal para no usar un border de CSS adecuado es para fines de animación.

Border Animations con outline-offset de Kevin J. Powell

Hace poco, un artículo que me llamó la atención es Fantastic CSS border animation, en el que la autora Coco analizó más opciones. Al insertar contenido generado con ::before y ::after, se crea un borde falso que luego se anima.

Lo que más me llama la atención son las visualizaciones animadas de apoyo utilizadas en el artículo. Realmente ayudan a explicar qué se está haciendo exactamente para lograr el efecto deseado.

Animaciones de bordes con contenido generado por Coco

Tanto la capa blanca como las líneas de colores son contenido generado. Al atenuar la capa blanca, queda claro cómo se apilan y cómo funciona la animación.

Cómo retener el modelo de caja

Una desventaja de usar contenido generado para imitar un borde es que terminarás con un modelo de cuadro roto: el contenido ahora puede oscurecer el borde falso porque dicho "borde" está pintado debajo. Para mitigar el problema, debes aplicar el border-width deseado como padding.

Para obtener un borde real y, así, conservar el funcionamiento del modelo de caja, puedes usar varios fondos, que luego extenderás en el área del borde.

Conceptos básicos

Comencemos por crear un borde punteado y agregar los múltiples fondos.

/* Size of the border */
--border-size: 0.5rem;

/* Create a dotted border */
border: var(--border-size) dotted lime;

/* Create two background layers:
   1. A white semi-transparent
   2. A layer with the colored boxes
 */
background-image:
  linear-gradient(to right, rgb(255 255 255 / 0.5), rgb(255 255 255 / 0.5)),

  conic-gradient(
    from 45deg,
    #d53e33 0deg 90deg,
    #fbb300 90deg 180deg,
    #377af5 180deg 270deg,
    #399953 270deg 360deg
  )
;

Ajusta el tamaño de los fondos con background-origin

Como puedes ver, sucede algo raro con los fondos aquí: están pintados en el borde, pero parece que la conic-gradient no es correcta. Este es el comportamiento previsto: de forma predeterminada, las imágenes de fondo no se dibujan en el borde, ya que su origen es el padding-box del elemento. Después de todo, para crear un borde, las imágenes de fondo configuradas se repiten en el borde, lo que produce un efecto visual extraño.

Para resolver este problema, debes estirar el fondo para que también ocupe el tamaño del borde. Para hacerlo de forma manual, puedes estirar y reposicionar el fondo, pero lo mejor es usar la propiedad background-origin para ajustar el tamaño del fondo en función de border-box.

Navegadores compatibles

  • 1
  • 12
  • 4
  • 3

Origen

Qué no debes hacer
/* Manually add or offset the size of the border where needed */
background-position: calc(var(--border-size) * -1) calc(var(--border-size) * -1);
background-size: calc(var(--border-size) * 2 + 100%) calc(var(--border-size) * 2 + 100%);
background-origin: border-box;

Con esta incorporación, todo se ve mucho mejor:

Se reduce la capa de fondo blanco con background-clip

Como los fondos ocupan todo el espacio ahora, la capa semitransparente debe volver a reducirse. En lugar de volver a manipular background-size, hay una manera más fácil de hacerlo: usa background-clip y establécelo en padding-box. De esa manera, el fondo ya no se dibujará debajo del área del borde.

Navegadores compatibles

  • 1
  • 12
  • 4
  • 5

Origen

background-clip:
  padding-box, /* Clip white semi-transparent to the padding-box */
  border-box /* Clip colored boxes to the border-box (default) */
;

Por último, crea el borde transparent para que tenga el efecto completo.

border: 0.3rem dotted transparent;

Animación

Para restablecer la animación del borde, puedes manipular el ángulo de inicio del conic-gradient.

--angle: 0deg;
conic-gradient(
  from var(--angle),
  #d53e33 0deg 90deg,
  #fbb300 90deg 180deg,
  #377af5 180deg 270deg,
  #399953 270deg 360deg
);

Gracias a @property, esto se facilita con los navegadores que lo admiten:

Navegadores compatibles

  • 85
  • 85
  • 16.4

Origen

@property --angle {
  syntax: "<angle>";
  initial-value: 0deg;
  inherits: false;
}

@keyframes rotate {
  to {
    --angle: 360deg;
  }
}

Si se combinan, el código se convierte en lo siguiente:

Contenido adicional: border-image

Un enfoque que vimos anteriormente para dibujar un borde gradiente es usar CSS border-image.

Navegadores compatibles

  • 16
  • 12
  • 15
  • 6

Origen

Permite un código más simplificado, ya que no necesitas lidiar con fondos superpuestos. La animación se puede aplicar de la misma manera que antes.

/* Create a border */
border: 0.5rem solid transparent;

/* Paint an image in the border */
border-image:
  conic-gradient(
    from var(--angle),
    #d53e33 0deg 90deg,
    #fbb300 90deg 180deg,
    #377af5 180deg 270deg,
    #399953 270deg 360deg
  ) 1
;

Sin embargo, notarás que algunos aspectos ya no funcionan con este enfoque:

  • El elemento border-image no sigue a la border-radius y siempre permanecerá rectangular.
  • Cuando se configura border-image-slice para que se complete, border-image no se pinta debajo del conjunto background, sino encima. Esto puede ser problemático si deseas que el fondo sea semitransparente.

En cierre

Existe una gran cantidad de posibilidades para animar bordes en CSS. Según el caso de uso, podrías recurrir a uno de ellos.