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.
outline-offset de Kevin J. PowellUn 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.
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.
/* 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;
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.
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:
@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.
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-imageno sigue elborder-radius; siempre permanecerá rectangular. - Cuando se configura
border-image-slicepara rellenar, elborder-imageno se pinta debajo delbackgroundestablecido, 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.