Skip to content

Tutto per WordPress, lo sviluppo web — e non solo

✨ Animare linee SVG e percorsi chiusi con puro CSS

✨ Animare linee SVG e percorsi chiusi con puro CSS

L'animazione del tratto SVG è una di quelle tecniche che trasforma un'icona statica in un'illustrazione viva. Avrai già visto questo effetto: il contorno di un logo si disegna da solo in modo fluido, come se una penna invisibile tracciasse la forma dall'inizio alla fine. Sembra costoso, ma si realizza con puro CSS.

Il problema è che la maggior parte dei tutorial si ferma al caso più semplice: un percorso aperto, una singola linea, animazione dall'inizio alla fine. Ma la grafica reale è fatta di contorni chiusi, forme spezzate e direzioni di disegno che il designer non ha controllato. Un tracciato SVG può iniziare in qualsiasi punto, e tu hai bisogno che si disegni in senso orario partendo da un punto di partenza esteticamente gradevole.

Qui sotto trovi la serie completa di tecniche: dall'animazione base alle doppie linee e al pieno controllo sui punti di inizio e fine. Tutto in puro CSS, senza librerie né misurazioni a runtime. Questi metodi sono stati testati durante lo sviluppo del plugin SVG Divider e funzionano in qualsiasi browser moderno.

💡 Panoramica rapida:

  • Trova la lunghezza del tracciato SVG tramite getTotalLength() o Illustrator e scrivi il numero nel CSS.
  • Imposta stroke-dasharray: LENGTH e anima stroke-dashoffset da LENGTH a 0.
  • Per invertire la direzione, scambia tratto e spazio in stroke-dasharray e sposta in avanti stroke-dashoffset.
  • Sposta il punto di partenza aggiungendo metà (o una qualsiasi frazione) della lunghezza a stroke-dashoffset.
  • Avvia l'animazione "inside-out": parti da HALF_LENGTH, arriva a FULL_LENGTH.
  • Imposta le doppie linee tramite stroke-dasharray a metà lunghezza e stroke-dashoffset spostato di un quarto.

Fondamenti tecnici: tratti, spazi e lunghezza del tracciato

Alla base di qualsiasi animazione SVG ci sono due proprietà CSS: stroke-dasharray e stroke-dashoffset. La prima definisce un pattern "tratto-spazio" lungo il contorno, la seconda sposta questo pattern. Se rendi il tratto uguale alla lunghezza totale del tracciato e poi animi l'offset, la linea si "disegna" davanti ai tuoi occhi.

Il passaggio chiave prima di qualsiasi animazione è trovare la lunghezza totale del tracciato. Metodi:

  • JavaScript: document.querySelector('path').getTotalLength(), una chiamata da console, il numero va scritto direttamente nel CSS. Nessun runtime.
  • Illustrator: il pannello "Informazioni documento" mostra la lunghezza del tracciato selezionato.
  • Script personalizzato: se hai decine o centinaia di tracciati, ha senso scrivere un'attraversamento automatico e la marcatura delle lunghezze.

Sfumatura importante: getTotalLength() e Illustrator possono dare numeri leggermente diversi per lo stesso tracciato. Il motivo è la diversa precisione di calcolo. La discrepanza è di solito entro 1-2 unità e non influisce sulla resa visiva.

Controlla la geometria del tracciato per eventuali errori. La direzione di disegno e il punto di partenza dipendono da come il designer ha costruito la curva nell'editor, è normale. Più avanti impareremo a controllare entrambi senza modificare l'SVG stesso.

Animazione base: disegnare una linea dall'inizio alla fine

Caso più semplice: un tracciato aperto con una lunghezza di, diciamo, 100 unità. Imposta il tratto alla lunghezza totale e anima l'offset da 100 a 0:

1@keyframes reveal {
2 to {
3 stroke-dashoffset: 0;
4 }
5}
6svg path {
7 stroke-dashoffset: 100;
8 stroke-dasharray: 100;
9 animation: reveal 1s ease-in-out 0s forwards;
10}

Cosa succede qui: stroke-dasharray: 100 imposta 100 unità di linea piena e 100 unità di spazio vuoto (il secondo valore è uguale al primo per impostazione predefinita). stroke-dashoffset: 100 sposta il pattern in modo che la parte visibile vada oltre i confini del tracciato, la linea è invisibile. L'animazione riduce l'offset a zero e il tratto si materializza nella sua posizione.

Alcune note pratiche:

  • Sostituisci FULL_LENGTH con il numero effettivo senza unità di misura. Il motore CSS non capisce px o em all'interno di stroke-dasharray.
  • Il selettore svg path è per un solo contorno. Se l'SVG ha più tracciati, usa classi, ID o pseudo-classi come path:nth-of-type(3). Strumenti di debug: :nth Tester e nthmaster.com.
  • Il nome di @keyframes deve essere unico per ogni variante di animazione. Tracciati diversi spesso richiedono keyframe propri.
  • Evita valori negativi di stroke-dashoffset: Safari può mostrare sfarfallii o artefatti con offset negativi.

Controllare la direzione: invertire il disegno

Per impostazione predefinita, l'animazione va dall'inizio alla fine del tracciato, ovunque il designer abbia disegnato la curva. Ma spesso serve l'opposto: un contorno chiuso che si disegna in senso orario anziché antiorario.

La soluzione è invertire il pattern del tratto: la linea inizia invisibile (0 tratto, 100 spazio) e diventa visibile (100 tratto, 0 spazio), mentre l'offset la tira indietro:

1@keyframes reversed {
2 from {
3 stroke-dasharray: 0 100;
4 stroke-dashoffset: 0;
5 }
6 to {
7 stroke-dasharray: 100 0;
8 stroke-dashoffset: 100;
9 }
10}
11svg path {
12 animation: reversed 1s ease-in-out 0s forwards;
13}

Il meccanismo funziona grazie alla natura ciclica del pattern del tratto: la linea piena si materializza alla fine del tracciato, mentre la sua copia va a sinistra oltre l'inizio e rimane invisibile. Lo stesso accade sui contorni chiusi: la copia del tratto appare "prima" dell'inizio e non interferisce con la percezione.

Esiste un approccio alternativo, più breve e senza manipolazione dell'array:

1@keyframes alternative-reversed {
2 from {
3 stroke-dashoffset: 100;
4 }
5 to {
6 stroke-dashoffset: 200;
7 }
8}
9svg path {
10 stroke-dasharray: 100;
11 animation: alternative-reversed 1s ease-in-out 0s forwards;
12}

Qui stroke-dasharray è fissato alla lunghezza totale, mentre l'offset va da 100 a 200. Stesso risultato, la linea si disegna in direzione inversa. Usa la variante che ti sembra più intuitiva.

Spostare il punto di partenza

Un tracciato chiuso è come una ferrovia circolare: il treno può partire da qualsiasi stazione. Il compito è spostare l'inizio dell'animazione in un punto esteticamente gradevole senza toccare la geometria stessa.

Partire dal lato opposto

Per contorni simmetrici, basta un offset di metà lunghezza:

1@keyframes start-from-other-side {
2 from {
3 stroke-dasharray: 0 100;
4 stroke-dashoffset: 50;
5 }
6 to {
7 stroke-dasharray: 100 0;
8 stroke-dashoffset: 50;
9 }
10}
11svg path {
12 animation: start-from-other-side 1s ease-in-out 0s forwards;
13}

La direzione di disegno resta quella originale, ma visivamente l'animazione parte dall'estremità opposta.

Invertire la direzione e punto di partenza arbitrario

Per invertire simultaneamente la direzione e spostare il punto di partenza, aggiungi la lunghezza totale all'offset finale:

1@keyframes other-side-and-reverse {
2 from {
3 stroke-dasharray: 0 100;
4 stroke-dashoffset: 50;
5 }
6 to {
7 stroke-dasharray: 100 0;
8 stroke-dashoffset: 150;
9 }
10}
11svg path {
12 animation: other-side-and-reverse 1s ease-in-out 0s forwards;
13}

Per un punto completamente arbitrario, sostituisci un valore qualsiasi al posto di 50. Prove ed errori (più o meno 5-10 unità) trovano la posizione ottimale. In un progetto, il punto di partenza su un'icona di bit di Twitch è stato spostato di 17 pixel, un numero brutto ma visivamente perfetto.

Animazione "inside-out"

La linea cresce dal centro in entrambe le direzioni simultaneamente, una tecnica classica per loghi e infografiche:

1@keyframes inside-out {
2 from {
3 stroke-dasharray: 0 100;
4 stroke-dashoffset: 50;
5 }
6 to {
7 stroke-dasharray: 100 0;
8 stroke-dashoffset: 100;
9 }
10}
11svg path {
12 animation: inside-out 1s ease-in-out 0s forwards;
13}

L'offset parte da metà lunghezza (centro del tracciato) e arriva alla lunghezza totale, trascinando il tratto con sé. Per forme asimmetriche, il punto di partenza può essere ulteriormente spostato:

1@keyframes custom-inside-out {
2 from {
3 stroke-dasharray: 0 100;
4 stroke-dashoffset: 84;
5 }
6 to {
7 stroke-dasharray: 100 0;
8 stroke-dashoffset: 134;
9 }
10}

Qui 84 = METÀ_LUNGHEZZA + 34. La costante 34 è scelta a mano per una forma specifica. Non esiste una ricetta universale: prova, guarda, regola.

Animazione "outside-in": doppia penna

L'approccio opposto: la linea si disegna da entrambe le estremità simultaneamente, convergendo verso il centro. Su contorni aperti questo dà un effetto "due penne":

1@keyframes outside-in {
2 from {
3 stroke-dasharray: 0 100;
4 }
5 to {
6 stroke-dasharray: 50 0;
7 }
8}
9svg path {
10 animation: outside-in 1s ease-in-out 0s forwards;
11}

Il tratto copre solo metà della lunghezza, il gap collassa due volte più velocemente che nell'animazione base. Qui stroke-dashoffset non serve: il pattern "0 gap" nello stato finale fa convergere da solo entrambe le metà del tratto.

Controllo totale: punti di inizio e fine

Quando una sola direzione e un solo punto di partenza non bastano, puoi controllare entrambi i confini del disegno. Due teste di linea in movimento convergono verso una destinazione comune:

1@keyframes custom-start-end {
2 from {
3 stroke-dasharray: 0 100;
4 stroke-dashoffset: 30;
5 }
6 to {
7 stroke-dasharray: 100 0;
8 stroke-dashoffset: 80;
9 }
10}
11svg path {
12 animation: custom-start-end 1s ease-in-out 0s forwards;
13}

I valori 30 e 80 sono arbitrari; l'unica regola fissa è che l'offset from sia minore dell'offset to. Se i punti sono vicini, un segmento vola veloce, l'altro striscia lentamente: è normale e persino bello.

Non aver paura di superare la lunghezza totale nel valore to. stroke-dashoffset: 130 con lunghezza 100 è legale, semplicemente sposta il ciclo del tratto al secondo giro. L'importante è evitare valori negativi.

Linee doppie ed effetti speciali

La modalità più flessibile: tratti a metà lunghezza con spostamento di un quarto. Ogni tracciato ottiene due teste di linea che si muovono indipendentemente:

1@keyframes double-lines {
2 from {
3 stroke-dasharray: 0 50;
4 stroke-dashoffset: 25;
5 }
6 to {
7 stroke-dasharray: 50 0;
8 stroke-dashoffset: 50;
9 }
10}
11svg path {
12 animation: double-lines 1s ease-in-out 0s forwards;
13}

Per forme complesse, l'array del tratto può essere composto da più componenti. La somma di tutti i valori dell'array deve essere uguale alla lunghezza totale. Esempio reale per un segno di infinito:

1@keyframes infinity-double-lines {
2 from {
3 stroke-dasharray: 0 53 0 47;
4 stroke-dashoffset: 37;
5 }
6 to {
7 stroke-dasharray: 53 0 47 0;
8 stroke-dashoffset: 60;
9 }
10}
11svg .infinity {
12 animation: infinity-double-lines 8s ease-in-out 0s alternate infinite;
13 stroke: #8D69D8;
14}

Quattro componenti dell'array (53 + 47 = 100 = lunghezza totale) si scambiano di posto tra from e to. L'animazione è in loop (infinite) e inverte la direzione (alternate), creando un contorno meditativo e pulsante che non si ripete mai in modo identico.

Video: animazione SVG in pratica

Per vedere dal vivo tutte le tecniche descritte e capire le sfumature di configurazione, guarda questo tutorial in inglese:

L'autore mostra passo passo la creazione di un'illustrazione SVG animata, dall'esportazione da Figma ai ritocchi finali in CSS. I timecode nella descrizione ti permettono di saltare direttamente alla sezione che ti serve.

⁉️🤔 Domande frequenti

Perché conoscere in anticipo la lunghezza del tracciato se esiste getTotalLength()?

getTotalLength() è JavaScript, e il nostro obiettivo è CSS puro senza dipendenze a runtime. Misuri la lunghezza UNA VOLTA (in console o in Illustrator), inserisci il numero direttamente nel CSS e l'animazione funziona senza una sola riga di JS.

Si possono animare più tracciati con una sola animazione?

Sì, se hanno la stessa lunghezza e lo stesso comportamento desiderato. Nella pratica i tracciati raramente coincidono, è più semplice dare a ciascuno i propri @keyframes o usare variabili CSS con valori di lunghezza diversi.

Perché Safari sfarfalla con stroke-dashoffset negativo?

È un bug noto del rendering WebKit: i valori di offset negativi a volte vengono interpretati come un azzeramento istantaneo. La soluzione è mantenere sempre stroke-dashoffset ≥ 0; se ti serve uno spostamento, aggiungi la lunghezza intera invece di andare in negativo.

Cosa fare se l'animazione "scatta" all'inizio o alla fine?

Aggiungi forwards a animation (mantiene lo stato finale) e rimuovi alternate se non ti serve l'inversione. Verifica anche eventuali conflitti con altre regole CSS per lo stesso elemento, ad esempio una transition sulla stessa proprietà.

Funziona con stroke-dasharray su contorni chiusi con geometria complessa?

Sì, la meccanica è la stessa per qualsiasi tracciato SVG, linee rette, curve di Bézier, poligoni chiusi. L'unica differenza è che su un contorno chiuso non c'è un "inizio" e una "fine" visivi, quindi controllare il punto di partenza è particolarmente importante per l'estetica.

Vale la pena scrivere l'animazione a mano quando esistono le librerie?

Risposta breve: dipende dalla scala. Per un'icona una tantum su una landing page, il controllo manuale dà risultati perfetti senza dipendenze extra. Quindici minuti per regolare un offset, e il contorno si disegna esattamente come lo avevi pensato, non come ha deciso lo sviluppatore della libreria.

Quando abbiamo realizzato i divisori SVG per Elementor, il controllo manuale ha ripagato tre volte tanto. Il plugin usa decine di divisori animati, ciascuno con tratti regolati individualmente. Nessuna libreria darebbe un tale controllo sull'estetica.

Oltre alle tecniche di questo articolo, puoi sovrapporre:

  • Controllo dello stato dell'animazione via JavaScript (avvio/stop/riavvio);
  • Avvio lazy tramite Intersection Observer, il contorno si disegna solo quando entra nel viewport;
  • Catene di animazioni tramite animation-delay;
  • Funzioni di easing personalizzate (cubic-bezier());
  • Lavoro aggiuntivo sull'opacità nei @keyframes;
  • Animazione elastica delle linee tratteggiate ("formiche che marciano").

Prendi gli schemi di questo articolo come base, sostituisci i tuoi valori di lunghezza e sperimenta con cubic-bezier(). Una funzione di easing scelta bene cambia la percezione dell'animazione più di quanto farebbe spostare il punto di partenza di un paio di pixel.