Analizziamo diversi modi per animare un bordo in CSS
Impostazione dei bordi
Esistono diversi metodi per impostare un bordo su un elemento: border
, outline
e box-shadow
. Come descritto in The 3 CSS Methods for Adding Element Borders di Stephanie Eckles, ogni approccio presenta vantaggi e svantaggi, in particolare per quanto riguarda l'animazione dei bordi. Il motivo principale per cui non utilizzare un border
CSS corretto è per l'animazione.
Un articolo che ha attirato la mia attenzione di recente è Fantastic CSS border animation, in cui l'autore Coco ha esplorato altre opzioni. Inserendo contenuti generati utilizzando ::before
e ::after
, creano un falso bordo che viene poi animato.
Ciò che mi colpisce di più sono le visualizzazioni animate di supporto utilizzate nell'articolo. ma aiutano a spiegare esattamente cosa viene fatto per ottenere l'effetto desiderato.
Sia il livello bianco che le linee colorate sono contenuti generati. Attraverso la dissolvenza il livello bianco in entrata e in uscita, diventa chiaro come si sovrappongono e come funziona l'animazione.
Mantenimento del modello a caselle
Uno svantaggio dell'utilizzo di contenuti generati per imitare un bordo è che si ottiene un modello di riquadro non funzionante: i contenuti ora possono oscurare il falso bordo perché questo "bordo" viene dipinto sotto. Per mitigare il problema, devi applicare il border-width
desiderato come padding
.
Per avere un bordo reale e mantenere così il funzionamento del modello a scatola, puoi utilizzare più sfondi che poi allungare nell'area del bordo.
Nozioni di base
Iniziamo creando un bordo a puntini e aggiungendo più sfondi.
/* 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
)
;
Regolare le dimensioni degli sfondi con background-origin
Come puoi vedere, c'è qualcosa di strano con gli sfondi: sono dipinti nel bordo, ma il conic-gradient
sembra essere tutto sbagliato. Questo è il comportamento previsto: per impostazione predefinita, le immagini di sfondo non disegnano il bordo perché la loro origine è il padding-box
dell'elemento. Per creare un bordo, le immagini di sfondo impostate vengono ripetute nel bordo stesso, producendo l'effetto visivo strano.
Per risolvere il problema, devi allungare lo sfondo in modo che occupi anche le dimensioni del bordo. Puoi farlo manualmente allungando e riposizionando lo sfondo, ma è meglio utilizzare la proprietà background-origin
per ridimensionare lo sfondo in base a 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;
Questa aggiunta rende tutto molto migliore:
Riduzione del livello di sfondo bianco con background-clip
Ora che gli sfondi occupano tutto lo spazio, il livello semitrasparente deve essere ridotto di nuovo. Anziché armeggiare di nuovo con background-size
, un modo più semplice per farlo è utilizzare background-clip
e impostarlo su padding-box
. In questo modo, lo sfondo non viene più disegnato sotto l'area del bordo.
background-clip:
padding-box, /* Clip white semi-transparent to the padding-box */
border-box /* Clip colored boxes to the border-box (default) */
;
Infine, imposta il bordo su transparent
per ottenere l'effetto completo.
border: 0.3rem dotted transparent;
Animazione
Per ripristinare l'animazione del bordo, puoi modificare l'angolo iniziale di conic-gradient
.
--angle: 0deg;
conic-gradient(
from var(--angle),
#d53e33 0deg 90deg,
#fbb300 90deg 180deg,
#377af5 180deg 270deg,
#399953 270deg 360deg
);
Grazie a @property, questa operazione diventa un gioco da ragazzi nei browser che la supportano:
@property --angle {
syntax: "<angle>";
initial-value: 0deg;
inherits: false;
}
@keyframes rotate {
to {
--angle: 360deg;
}
}
Se li combini tutti, il codice diventa:
Contenuti bonus: border-image
Un approccio trattato in precedenza per disegnare un bordo con sfumatura è utilizzare CSS border-image
.
Consente di avere un codice più semplificato in quanto non è necessario gestire sfondi sovrapposti. L'animazione può essere applicata come prima.
/* 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
;
Tuttavia, noterai che alcune funzionalità non funzionano più con questo approccio:
border-image
non segueborder-radius
; rimarrà sempre rettangolare.- Quando imposti
border-image-slice
per riempire lo spazio,border-image
non viene dipinto sotto l'insiemebackground
, ma sopra. Questo può essere problematico se vuoi che lo sfondo sia semitrasparente.
In conclusione
Esistono moltissime possibilità per animare i bordi in CSS. A seconda dei casi d'uso, potresti affidarti all'uno o all'altro.