Animazioni dei bordi CSS

Vediamo diversi modi per animare un bordo in CSS

Impostazione dei bordi

Esistono alcuni metodi per impostare il bordo di un elemento: border, outline e box-shadow. Come descritto in I 3 metodi CSS per aggiungere i bordi degli elementi di Stephanie Eckles, ciascun approccio presenta vantaggi e svantaggi, in particolare per quanto riguarda l'animazione dei bordi. Il motivo principale per non utilizzare un border CSS corretto è per scopi di animazione.

Animazioni dei bordi con outline-offset di Kevin J. Powell

Un articolo che di recente ha attirato la mia attenzione è Fantastica animazione di bordo CSS, in cui l'autore Coco ha esplorato altre opzioni. Inserendo contenuti generati con ::before e ::after, viene creato un bordo finto che viene poi animato.

Quello che mi colpisce di più sono le visualizzazioni animate di supporto utilizzate nell'articolo. Aiutano davvero a spiegare cosa viene fatto esattamente per ottenere l'effetto desiderato.

Animazioni dei bordi con contenuti generati da Coco

Sia il livello bianco che le linee colorate vengono generati contenuti. Facendo una dissolvenza del livello bianco in entrata e in uscita, diventa chiaro come si sovrappongono e come funziona l'animazione.

Conservazione del modello della scatola

Uno svantaggio dell'utilizzo di contenuti generati per imitare un bordo è il fatto che si finisce con un modello a scatola rotto: i contenuti ora possono oscurare il bordo finto perché è stato dipinto il "bordo" sotto. Per mitigare, devi applicare il border-width desiderato come padding.

Per avere un bordo reale e quindi mantenere il funzionamento del modello a riquadro, puoi utilizzare più sfondi che poi ampliano l'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
  )
;

Ridimensionamento degli sfondi con background-origin

Come puoi vedere, c'è qualcosa di divertente con gli sfondi qui: sono dipinti sul bordo, ma il conic-gradient sembra essere tutto sbagliato. Questo è effettivamente il comportamento previsto: per impostazione predefinita le immagini di sfondo non vengono tracciate sul bordo poiché la loro origine è il padding-box dell'elemento. Dopotutto, per creare un bordo, le immagini di sfondo impostate vengono ripetute nel bordo stesso, generando uno strano effetto visivo.

Per risolvere il problema, devi estendere lo sfondo in modo che occupi anche le dimensioni del bordo. Puoi farlo manualmente estendendo e riposizionando lo sfondo, ma la soluzione migliore è utilizzare la proprietà background-origin per ridimensionare lo sfondo in base a border-box.

Supporto dei browser

  • 1
  • 12
  • 4
  • 3

Fonte

Cosa non fare
/* 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%);
Cosa fare
background-origin: border-box;

Con questa sola aggiunta, tutto è molto più bello:

Riduce il livello di sfondo bianco con background-clip

Ora che gli sfondi occupano tutto lo spazio, il livello semitrasparente deve essere ridotto di nuovo. Invece di armeggiare di nuovo con background-size, c'è un modo più semplice per farlo: usa background-clip e impostalo su padding-box. In questo modo lo sfondo non viene più tracciato sotto l'area del bordo.

Supporto dei browser

  • 1
  • 12
  • 4
  • 5

Fonte

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 transparent per ottenere il massimo effetto.

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 questo diventa un gioco da ragazzi nei browser che lo supportano:

Supporto dei browser

  • 85
  • 85
  • 16.4

Fonte

@property --angle {
  syntax: "<angle>";
  initial-value: 0deg;
  inherits: false;
}

@keyframes rotate {
  to {
    --angle: 360deg;
  }
}

Combinando questi dati, il codice diventa questo:

Contenuti bonus: border-image

Un approccio trattato in precedenza per tracciare un bordo gradiente è utilizzare il CSS border-image.

Supporto dei browser

  • 16
  • 12
  • 15
  • 6

Fonte

In questo modo, è possibile semplificare il codice 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 alcuni elementi non funzionano più con questo approccio:

  • border-image non segue il border-radius; rimarrà sempre rettangolare.
  • Quando imposti border-image-slice per la riempimento, la border-image non viene visualizzata sotto il set background, ma in alto. Questo può essere problematico se vuoi che lo sfondo sia semitrasparente.

In chiusura

Le possibilità di animare i bordi in CSS sono molteplici. A seconda del caso d'uso, ci si potrebbe affidare all'una o all'altro.