Skip to content

Allt om WordPress, webbutveckling — och mer därtill

✨ Animera SVG-linjer och slutna banor med ren CSS

✨ Animera SVG-linjer och slutna banor med ren CSS

SVG-stroke-animation är en av de tekniker som förvandlar en statisk ikon till en levande illustration. Du har säkert sett effekten: en logotyps kontur ritar sig själv mjukt, som om en osynlig penna följer formen från början till slut. Det ser påkostat ut, men görs med ren CSS.

Problemet är att de flesta guider stannar vid det enklaste fallet: en öppen bana, en enda linje, animation från start till slut. Men verklig grafik innehåller slutna konturer, brutna former och ritriktningar som designern inte kontrollerade. En SVG-bana kan börja var som helst, och du behöver att den ritas medurs från en estetiskt tilltalande startpunkt.

Här nedan följer den kompletta uppsättningen tekniker: från grundläggande animation till dubbla linjer och full kontroll över start- och slutpunkter. Allt i ren CSS, inga bibliotek eller körtidsmätningar. Metoderna testades under utvecklingen av SVG Divider-plugin och fungerar i alla moderna webbläsare.

💡 Snabb översikt:

  • Hitta SVG-banans längd via getTotalLength() eller Illustrator och skriv in siffran i CSS.
  • Sätt stroke-dasharray: LENGTH och animera stroke-dashoffset från LENGTH till 0.
  • För att vända riktning, byt plats på stroke och gap i stroke-dasharray och skjut stroke-dashoffset framåt.
  • Flytta startpunkten genom att lägga till halva (eller valfri andel av) längden till stroke-dashoffset.
  • Starta "inifrån-och-ut"-animation: börja från HALF_LENGTH, avsluta vid FULL_LENGTH.
  • Sätt upp dubbla linjer via stroke-dasharray med halva längden och stroke-dashoffset med en kvarts förskjutning.

Teknisk grund: strokes, gap och banlängd

Kärnan i all SVG-animation är två CSS-egenskaper: stroke-dasharray och stroke-dashoffset. Den första definierar ett "stroke-gap"-mönster längs konturen, den andra förskjuter detta mönster. Om du gör stroken lika med hela banlängden och sedan animerar förskjutningen, "ritas" linjen framför dina ögon.

Det avgörande steget före all animation är att ta reda på hela banlängden. Metoder:

  • JavaScript: document.querySelector('path').getTotalLength(), ett konsolanrop, siffran hårdkodas in i CSS. Ingen körtid.
  • Illustrator: panelen "Dokumentinfo" visar längden på den markerade banan.
  • Anpassat skript: om du har dussintals eller hundratals banor är det vettigt att skriva automatisk genomgång och längdmärkning.

Viktig nyans: getTotalLength() och Illustrator kan ge något olika siffror för samma bana. Orsaken är olika beräkningsprecision. Avvikelsen ligger vanligtvis inom 1-2 enheter och påverkar inte det visuella.

Kontrollera bangeometrin efter fel. Ritriktning och startpunkt beror på hur designern byggde kurvan i editorn, det är normalt. Nedan lär vi oss att styra båda utan att redigera själva SVG:n.

Grundläggande animation: rita en linje från start till slut

Enklaste fallet: en öppen bana med en längd på, säg, 100 enheter. Sätt stroken till full längd och animera förskjutningen från 100 till 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}

Vad som händer här: stroke-dasharray: 100 sätter 100 enheter heldragen linje och 100 enheter tomrum (det andra värdet blir samma som det första). stroke-dashoffset: 100 förskjuter mönstret så att den synliga delen hamnar utanför banans gränser, linjen är osynlig. Animationen minskar förskjutningen till noll, och stroken kryper på plats.

Några praktiska noteringar:

  • Ersätt FULL_LENGTH med det faktiska talet utan måttenhet. CSS-motorn förstår inte px eller em inuti stroke-dasharray.
  • Selektor svg path är för en kontur. Om SVG:n har flera banor, använd klasser, ID:n eller pseudoklasser som path:nth-of-type(3). Felsökningsverktyg: :nth Tester och nthmaster.com.
  • Namnet på @keyframes måste vara unikt för varje animationsvariant. Olika banor kräver ofta sina egna keyframes.
  • Undvik negativa stroke-dashoffset-värden: Safari kan flimra eller visa artefakter med negativa förskjutningar.

Kontrollera riktning: vända ritningen

Som standard går animationen från banans start till slut, varhelst designern ritade kurvan. Men du behöver ofta motsatsen: en sluten kontur som ritas medurs istället för moturs.

Lösningen är att invertera stroke-mönstret: linjen börjar osynlig (0 stroke, 100 gap) och blir synlig (100 stroke, 0 gap), medan förskjutningen drar den bakåt:

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}

Mekaniken fungerar genom stroke-mönstrets cykliska natur: den heldragna linjen materialiseras vid banans slut, medan dess kopia går åt vänster bortom starten och förblir osynlig. Samma sak sker på slutna konturer: stroke-kopian dyker upp "före" starten och stör inte upplevelsen.

Det finns en alternativ metod, kortare och utan arraymanipulation:

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}

Här är stroke-dasharray fast på hela längden, medan offset går från 100 till 200. Samma resultat, linjen ritas i omvänd riktning. Använd den variant som känns mest intuitiv för dig.

Flytta startpunkten

En sluten bana är som en cirkulär järnväg: tåget kan starta från vilken station som helst. Uppgiften är att flytta animationens start till en estetiskt tilltalande punkt utan att röra själva geometrin.

Starta från motsatt sida

För symmetriska konturer räcker det med halva längden som offset:

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}

Ritriktningen förblir den ursprungliga, men visuellt startar animationen från den motsatta änden.

Vända riktning och godtycklig start

För att samtidigt vända riktning och flytta startpunkten, lägg till hela längden till slut-offset:

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}

För en helt godtycklig punkt, ersätt 50 med valfritt värde. Trial and error (plus eller minus 5-10 enheter) hittar den optimala positionen. I ett projekt flyttades startpunkten på en Twitch bit-ikon med 17 pixlar, en ful siffra men visuellt perfekt.

"Inifrån och ut"-animation

Linjen växer från mitten i båda riktningarna samtidigt, en klassisk teknik för logotyper och infografik:

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}

Offset startar från halva längden (banans mitt) och går till hela längden, och drar med sig linjen. För asymmetriska former kan startpunkten förskjutas ytterligare:

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}

Här är 84 = HALF_LENGTH + 34. Konstanten 34 är handplockad för en specifik form. Det finns inget universellt recept, prova, titta, justera.

"Utifrån och in"-animation: dubbel penna

Det motsatta angreppssättet: linjen ritas från båda ändarna samtidigt och möts i mitten. På öppna konturer ger detta en "två pennor"-effekt:

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}

Linjen når bara halva längden, gapet kollapsar dubbelt så snabbt som i grundanimationen. stroke-dashoffset behövs inte här: "0 gap"-mönstret i sluttillståndet får i sig självt båda linjehalvorna att konvergera.

Full kontroll: start- och slutpunkter

När en riktning och en startpunkt inte räcker kan du styra båda ritgränserna. Två rörliga linjehuvuden konvergerar mot ett gemensamt mål:

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}

Värdena 30 och 80 är godtyckliga; from-offset mindre än to-offset är den enda hårda regeln. Om punkterna ligger nära varandra flyger ett segment snabbt, det andra kryper långsamt, det är normalt och till och med vackert.

Var inte rädd för att gå bortom hela längden i to-värdet. stroke-dashoffset: 130 med längd 100 är tillåtet, det förskjuter bara linjecykeln till nästa varv. Huvudsaken är att undvika negativa värden.

Dubbla linjer och specialeffekter

Det mest flexibla läget: halvlånga linjer med kvartsförskjutning. Varje bana får två linjehuvuden som rör sig oberoende av varandra:

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}

För komplexa former kan linje-arrayen bestå av flera komponenter. Summan av alla array-värden ska vara lika med hela längden. Verkligt exempel för ett oändlighetstecken:

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}

Fyra array-komponenter (53 + 47 = 100 = hela längden) byter plats mellan from och to. Animationen loopar (infinite) och vänder (alternate), vilket skapar en meditativt andande kontur som aldrig upprepas identiskt.

Video: SVG-animering i praktiken

För att se alla beskrivna tekniker live och förstå nyanserna i uppsättningen, titta på den här engelska handledningen:

Författaren visar steg för steg hur man skapar en animerad SVG-illustration, från export från Figma till sista CSS-justeringar. Tidskoder i beskrivningen låter dig hoppa direkt till det avsnitt du behöver.

⁉️🤔 Vanliga frågor

*Varför behöver man veta banans längd i förväg när det finns getTotalLength()?*

getTotalLength() är JavaScript, och vårt mål är ren CSS utan beroenden vid körning. Du mäter längden EN GÅNG (i konsolen eller Illustrator), hårdkodar värdet i CSS, och animeringen fungerar utan en enda rad JS.

Kan man animera flera banor med en och samma animering?

Ja, om de har samma längd och önskat beteende. I praktiken matchar banor sällan varandra, det är enklare att ge var och en sin egen @keyframes eller använda CSS-variabler med olika längdvärden.

*Varför flimrar det i Safari med negativ stroke-dashoffset?*

Det är en känd renderingsbugg i WebKit: negativa offsetvärden tolkas ibland som en omedelbar återställning till 0. Lösningen är att alltid hålla stroke-dashoffset ≥ 0, om du behöver en förskjutning, lägg till hela längden istället för att gå negativt.

Vad gör man om animeringen "rycker" i början eller slutet?

Lägg till forwards i animation (bevarar sluttillståndet) och ta bort alternate om du inte behöver reversering. Kontrollera också om det finns konflikter med andra CSS-regler för samma element, till exempel transition på samma egenskap.

Fungerar detta med stroke-dasharray på slutna konturer med komplex geometri?

Ja, mekaniken är densamma för alla SVG-banor, raka linjer, Bezier-kurvor, slutna polygoner. Enda skillnaden är att det på en sluten kontur inte finns någon visuell "början" och "slut", så kontroll över startpunkten är särskilt viktig för estetiken.

Är det värt att skriva animering manuellt när det finns bibliotek?

Kort svar: beror på skalan. För en enstaka ikon på en landningssida ger manuell kontroll perfekta resultat utan extra beroenden. Femton minuter för att justera en offset, och konturen ritas upp precis som du tänkt dig, inte som biblioteksutvecklaren bestämde.

När vi skapade SVG-delare för Elementor lönade sig manuell kontroll tre gånger om. Pluginet använder dussintals animerade delare, var och en med individuellt inställda linjer. Inget bibliotek skulle ge sådan kontroll över estetiken.

Utöver teknikerna från den här artikeln kan du lägga på:

  • Kontroll av animeringstillstånd via JavaScript (start/stopp/omstart);
  • Lat laddning via Intersection Observer, konturen ritas bara upp när den kommer in i vyporten;
  • Animeringskedjor via animation-delay;
  • Anpassade easing-funktioner (cubic-bezier());
  • Ytterligare opacitetsarbete i @keyframes;
  • Elastisk animering av streckade linjer ("marscherande myror").

Ta ritningarna från den här artikeln som grund, byt ut dina längdvärden och experimentera med cubic-bezier(). En rätt vald easing-funktion förändrar upplevelsen av animeringen mer än att flytta startpunkten ett par pixlar.