Cómo analizar varias formas de animar un borde en CSS
Cómo establecer bordes
Hay 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 para la animación.
Un artículo que me llamó la atención recientemente es Fantastic CSS border animation, en el que la autora Coco exploró más opciones. Cuando se inyecta 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 respaldo que se usan en el artículo. Ayudan a explicar exactamente qué se está haciendo para lograr el efecto deseado.
Tanto la capa blanca como las líneas de colores son contenido generado. Cuando se atenúa la capa blanca, se aclara cómo se apilan y cómo funciona la animación.
Retención del modelo de cuadro
Una desventaja de usar contenido generado para imitar un borde es que terminas con un modelo de cuadro roto: el contenido ahora puede ocultar el borde falso porque ese "borde" se pinta debajo. Para mitigarlo, debes aplicar el border-width
deseado como padding
.
Para tener un borde real y, así, conservar el funcionamiento del modelo de cuadro, puedes usar varios fondos que luego estirarás en el área del borde.
Conceptos básicos
Comencemos por crear un borde con puntos 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
)
;
Cómo cambiar 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 todo 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. Después de todo, para crear un borde, las imágenes de fondo establecidas se repiten en el borde, lo que genera un efecto visual extraño.
Para resolver este problema, debes estirar el fondo para que también ocupe el tamaño del borde. Puedes hacerlo de forma manual estirando y cambiando la posición del fondo, pero lo mejor es usar la propiedad background-origin
para ajustar el tamaño del fondo en relación con 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;
Este solo agregado hace que todo se vea mucho mejor:
Reducción de la capa de fondo blanco con background-clip
Ahora que los fondos 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 configúralo 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, establece 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 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;
}
}
Todo junto, el código se convierte en lo siguiente:
Contenido adicional: border-image
Un enfoque que ya se analizó para dibujar un borde de gradiente es usar CSS border-image
.
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 elementos ya no funcionan con este enfoque:
- El
border-image
no sigue elborder-radius
; siempre será rectangular. - Cuando se establece
border-image-slice
para que se llene, elborder-image
no se pinta debajo del conjuntobackground
, sino en la parte superior. Esto puede ser problemático si quieres que el fondo sea semitransparente.
Para finalizar
Hay una gran cantidad de posibilidades para animar bordes en CSS. Según el caso de uso, puedes usar uno o el otro.