para crear un boton con un borde animado hay que tener algo en cuenta y es:
Los bordes en css no son una propiedad que se pueda animar.
entonces como hacer para que el borde de nuestro boton sea animado? hay que jugar un poquito con css y sus propiedades.
entonces vamos a iniciar creando un div, con una clase btn, ya que queremos que se vea como un boton, pero se puede usar cualquier html tag.
<divclass="btn">boton animado</div>
luego de tener nuestro div, o boton o lo que sea, yo en mi use case real (en donde use este truquito, use un span y no un boton, aunque cabe destacar que quizas sea una mala practica ya que un <button>tiene mas semantica que el span peero en fin).
Ahora vamos a agregar el css que es un poquito engañoso.
primero vamos a agregar una propiedad custom usando la directiva “@property” que nos deja crear una una variable con un valor tal cual justo hacemos con:
:root{
--custom-var : var-value
}
la diferencia aqui es que al usar “@property” le podemos decir al navegador que tipo de dato es esa variable, y de esta forma el navegador sabe en este caso que es una propiedad animable¿ si es que asi se dice…
@property --custom-value {
syntax: "<angle>";
initial-value: 0deg;
inherits: false;
}
recuerdas que te dije que lograr esto era un poco tricky? aunque use “engañoso” y es por que para lograr este efecto hay que usar un pseudoelemento, que puede ser ::after o puede ser ::before, da lo mismo.
antes de que se me olvide, lo que hicimos antes fue declarar un valor custom, y le decimos al browser que es de tipo angulo **<angle></angle>**y que comienza en 0deg es decir 0 grados de rotacion que ya veran el por qué.
entonces ahora usaremos el pseudoelemento “::after” para lograr crear el efecto borde pero en realidad lo que haremos sera crear una capa debajo de nuestro div que tenga los colores y la animacion que deseemos agregar.
primero le diremos que el div tendra una posicion relativa para poder digamos “pegarle” el pseudoelemento encima aunque en este caso sera una capa mas atras y para eso usaremos el z-index.
y le daremos unas propiedades basicas para que se vea como un boton.
.btn {
background: white;
border-radius:8px;
padding: 8px4px;
color: black;
position: relative;
z-index: 99;
}
asi lo que estamos diciendo es, vea, a este div de clase btn, yo quiero posicionarlo de manera relativa (en este caso no lo estamos moviendo con ninguna propiedad top, left, right or bottom) pero lo que si podemos hacer es digamos anidarle otro objeto que este posicionado de manera relativa a este, es decir que lo tome como referencia para moverse dentro de la pantalla y ahora crearemos el pseudo elemento.
.btn::after {
content: ' ';
position: absolute;
inset: -2px;
border-radius: inherit;
z-index: -1;
background: conic-gradient(
from var(--gradient-angle),
rgb(253, 32, 80),
rgb(38, 4, 4),
rgb(253, 32, 80)
);
animation: rotation 2s linear infinite;
}
entonces voy a romper en partes lo que hicimos aqui para explicarte:
content: ' ';
para que el browser renderice un pseudo elemento este debe tener un contenido o un width y aqui le estamos diciendo que va tener por contenido un string vacio 😉.
position: absolute;
aca le estamos diciendo que queremos mutar su posicion, dandole un valor absoluto es decir que va atomar como referencia la pantalla PEEERO como a su elemento padre que en este caso es el div class=‘btn’ le dimos un posicion relative, va a tomar como referencia para su posicion a este div.
inset: -2px;
y con la propiedad inset que basicamente es un shorthand para: top, left, bottom y right, le estamos diciendo que va a a excederse de el limite de lo que ocupa el elemento padre 2px por cada lado, por que?.
por que cuando usas una prop por ejemplo top y le dices que quieres alejarlo 2px del top que tenga como referencia (el elemento padre, o la ventana del navegador) va alejar el elemento hacia abajo y no hacia arriba, es decir basicamente hacia adentro, entonces si por cada lado le decimos que tenga un valor negativo, como -2px lo que hara es alejarlo hacia afuera, lo que hara que el pseudoelemento sobresalga 2px por cada lado del elemento padre y ya veran esto es lo que creara el efecto borde.
border-radius: inherit;
importante poero no tanto, aqui le decimos que tome el mismo border radius que su padre, si el elemento es cuadrado este sera cuadrado, si el elemento tiene 2px de border-radius el pseudoelemento tambien y asi sucesivamente.
z-index: -1;
con el z-index si alguna vez han usado figma, canvas o photoshop es como editar la capa en la que se encuentra el elemento, a mayor el numero, pues mas “al frente” estara el elemento. por eso el div tiene un z-index:99 mientras que el psudoelemtento tiene un z-index negativo, para que siempre este por detras del elemento padre y no por encima.
background: conic-gradient(
fromvar(--gradient-angle),
rgb(253, 32, 80),
rgb(38, 4, 4),
rgb(253, 32, 80)
);
esta es un poco mas complicada, aqui le diremos que el background del pseudoelemento sera un gradient, pero un gradient conico, es decir casi circular, por que casi? por que es un cono y no un circulo, cuando lleven esto a la practica veran de que hablo. entonces un gradient conico, que empieza: “from var(–gradient-angle)” aca estamos usando la variable que establecimos al inicio usando el @property. y luego especificamos 3 colores que podrian ser los que tu quieras, siempre y cuando el primer color y el ultimo sean el mismo, ya que al ser un efecto conico queda un poco raro por que no une inicio con final y sino salta de un color a otro, entonces es como un pequeño hack xd
animation: rotation 2s linear infinite;
y aqui le estamos diciendo que vamos a usar una animacion, la cual sera “rotation” que aun no hemos declarado, que esta va a durar 2s que su velocidad sera lineal, es decir siempre ira a la misma velocidad y su ciclo de repeticiones va a ser infinito.
@keyframes rotation {
0% {
--gradient-angle: 0deg;
}
100% {
--gradient-angle: 360deg;
}
}
usando la directiva @keyframe, basicamente estamos diciendo que crearemos una animacion de nombre "rotation"
y que en el 0% de la animacion cuando inicia la propiedad custom que creamos antes (y que es animable) empieza en 0deg y al 100% cuando termina estara en 360deg es decir que habra dado una vuelta o que habra rotado en su totalidad.
ahora que has llegado hasta el final tu css deberia verse asi:
.btn {
background: white;
border-radius:8px;
padding: 8px4px;
color: black;
position: relative;
z-index: 99;
}
.btn::after {
content: ' ';
position: absolute;
inset: -2px;
border-radius: inherit;
z-index: -1;
background: conic-gradient(
from var(--gradient-angle),
rgb(253, 32, 80),
rgb(38, 4, 4),
rgb(253, 32, 80)
);
animation: rotation 2s linear infinite;
}
@keyframes rotation {
0% {
--gradient-angle: 0deg;
}
100% {
--gradient-angle: 360deg;
}
}
intente compartir una imagen para que vieran el resultado pero soy nuevo en esto y ps no se pudo.
si quieren jugar con el ancho del borde, que sea mas o menos grueso, juegen con la cantidad de pixeles en la propiedad inset, a mayor el numero (en negativos) mas grueso sera el borde, y cuanto mas cerca del 0 mas fino sera.
gracias por llegar hasta aqui 😄