Animaciones de bordes CSS

Varias formas de animar un borde en CSS

Cómo establecer bordes

Existen algunos métodos disponibles para establecer un borde en un elemento: border, outline y box-shadow. Como se detalla en The 3 CSS Methods for Adding Element Borders 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 con fines de animación.

Border Animations using outline-offset de Kevin J. Powell

Un artículo que me llamó la atención recientemente es Fantastic CSS border animation, en el que el autor Coco exploró más opciones. Inyectando contenido generado con ::before y ::after, crean un borde falso que luego se anima.

Lo que más me llama la atención son las visualizaciones animadas de apoyo que se usan 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 color son contenido generado. Si se atenúa la capa blanca, se puede ver claramente cómo se apilan y cómo funciona la animación.

Cómo conservar el modelo de cuadro

Una desventaja de usar contenido generado para imitar un borde es que terminas con un modelo de caja roto: el contenido ahora puede ocultar el borde falso porque dicho "borde" se pinta debajo. Para mitigar, debes aplicar el border-width deseado como padding.

Para tener un borde verdadero y, por lo tanto, conservar el funcionamiento del modelo de cuadro, puedes usar varios fondos que luego estiras 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
  )
;

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

Como puedes ver, hay algo extraño con los fondos: están pintados en el borde, pero el conic-gradient parece estar mal. En realidad, 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. Para crear un borde, las imágenes de fondo establecidas se repiten en el borde, lo que produce un efecto visual extraño.

Para resolver este problema, debes estirar el fondo de modo que también ocupe el tamaño del borde. Podrías hacerlo de forma manual estirando y reposicionando el fondo, pero lo mejor es usar la propiedad background-origin para ajustar el tamaño del fondo en relación con el border-box.

Browser Support

  • Chrome: 1.
  • Edge: 12.
  • Firefox: 4.
  • Safari: 3.

Source

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%);
Qué debes hacer
background-origin: border-box;

Esta adición hace que todo se vea mucho mejor:

Reducción de la capa de fondo blanca con background-clip

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

Browser Support

  • Chrome: 1.
  • Edge: 12.
  • Firefox: 4.
  • Safari: 5.

Source

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

Por último, haz que el borde sea 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 de 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 vuelve muy sencillo en los navegadores que lo admiten:

Browser Support

  • Chrome: 85.
  • Edge: 85.
  • Firefox: 128.
  • Safari: 16.4.

Source

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

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

Si se combina todo, el código queda de la siguiente manera:

Contenido adicional: border-image

Un enfoque que ya se abordó para dibujar un borde con gradiente es usar border-image de CSS.

Browser Support

  • Chrome: 16.
  • Edge: 12.
  • Firefox: 15.
  • Safari: 6.

Source

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 algunas cosas ya no funcionan con este enfoque:

  • El border-image no sigue el border-radius; siempre permanecerá rectangular.
  • Cuando se configura border-image-slice para rellenar, el border-image no se pinta debajo del background establecido, sino en la parte superior. Esto puede ser problemático si quieres que el fondo sea semitransparente.

En conclusión

Hay muchas posibilidades para animar bordes en CSS. Según el caso de uso, es posible que te inclines por una o por otra.