Esaminare diversi modi per animare un bordo in CSS
Impostazione dei bordi
Esistono alcuni metodi disponibili 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, soprattutto quando si tratta di animare i bordi. Il motivo principale per non utilizzare un border CSS appropriato è legato alle animazioni.
outline-offset di Kevin J. PowellUn 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 bordo finto che viene poi animato.
Ciò che mi colpisce di più sono le visualizzazioni animate di supporto utilizzate nell'articolo. Sono davvero utili per spiegare esattamente cosa viene fatto per ottenere l'effetto desiderato.
Sia lo strato bianco che le linee colorate sono contenuti generati. La dissolvenza in entrata e in uscita del livello bianco mostra chiaramente come si sovrappongono e come funziona l'animazione.
Mantenimento del modello di box
Uno svantaggio dell'utilizzo dei contenuti generati per imitare un bordo è che si ottiene un box model non funzionante: i contenuti possono ora oscurare il bordo finto perché il "bordo" viene disegnato 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 di scatola, puoi utilizzare più sfondi che poi estendi nell'area del bordo.
Nozioni di base
Iniziamo creando un bordo tratteggiato 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
)
;
Dimensionamento 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 completamente sbagliato. Questo è in realtà il comportamento previsto: per impostazione predefinita, le immagini di sfondo non vengono disegnate nel bordo, poiché la loro origine è il padding-box dell'elemento. Per creare un bordo, le immagini di sfondo impostate vengono ripetute nel bordo stesso, producendo lo strano effetto visivo.
Per risolvere questo problema, devi estendere 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 rispetto 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 più bello:
Riduzione del livello di sfondo bianco con background-clip
Poiché gli sfondi occupano tutto lo spazio, lo strato semitrasparente deve essere nuovamente ridotto. Anziché modificare di nuovo background-size, esiste un modo più semplice per farlo: utilizza background-clip e impostalo 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 manipolare 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;
}
}
Nel complesso, il codice diventa il seguente:
Contenuti bonus: border-image
Un approccio trattato in precedenza per disegnare un bordo con gradiente consiste nell'utilizzare la proprietà CSS border-image.
Consente di semplificare il codice, in quanto non è necessario gestire sfondi sovrapposti. L'animazione può essere applicata nello stesso modo di 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 cose non funzionano più con questo approccio:
border-imagenon segueborder-radius, ma rimane sempre rettangolare.- Quando imposti
border-image-slicesu fill,border-imagenon viene disegnato sottobackground, ma sopra. Questo può essere un problema se vuoi che lo sfondo sia semitrasparente.
In conclusione
Esistono moltissime possibilità per animare i bordi in CSS. A seconda del caso d'uso, potresti preferire l'uno o l'altro.