Work in progress!
Recipe: How to animate lines in SVGs
Hi! This articles gives you a high-level overview of what you need to know to animate lines in an SVG without being forced to use any framework or library like React or D3. My goal is for you to be able to apply this technique to your custom stack.
If you are interested in applying this technique with React and D3 however, check out this video.
svgcontaining any other SVG element like
stroke-dasharray(an attribute on SVG DOM elements)
stroke-dashoffset(an attribute on SVG DOM elements)
- a sprinkle of CSS
getTotalLength(a method on any SVG DOM element)
Let's get started!
SVG elements have 2 important properties: A stroke, and filling (or fill).
The stroke is what we want to animate, and the trick behind animating those lines is with the
stroke-dashoffset attributes, which you can put on any SVG element, such as
path and even on the
The magic trick
The stroke-dasharray attribute determines how a stroke is dashed and is described with 2 numbers, like so: stroke-dasharray="10 2". The first number determines the length of each dash (line), while the second number determines the length of the following gap. This pattern (dash, gap, dash, gap ...) is repeated indefinitely.
// will render a dashed line (each dash being 10px) // on an 300x150px svg (default dimensions) <svg> <line x1="0" y1="0" x2="300" y2="150" stroke-dasharray="10 50" stroke="black" /> </svg>
The stroke-dashoffset attribute adds an offset to the stroke-dasharray pattern, and moves it along the stroke for a given length. If the stroke-dasharray is "100 100", the stroke will start with a 100px dash, which will be followed by a 100px gap. Now, if a stroke-dashoffset of "100" is added, the stroke will start with the gap instead, which then will be followed by the dash, and so on.
// will render a dashed line (each dash being 10px) // on an 300x150px svg (default dimensions) <svg> <line x1="0" y1="0" x2="300" y2="150" stroke="black" stroke-dasharray="100 100" stroke-dashoffset="0" style="transition: stroke-dashoffset 0.5s" /> </svg>
Now think of a stroke which has a total length of 100px, and you give it a dasharray of "100 100". This will result in a solid line (no dashes), because the first dash of the dasharray is as long as the entire stroke itself. The following gap is there and just as long as the dash, but is irrelevant, because it starts just where the stroke ends.
Adding a stroke-dashoffset of 100 will turn the tables. The dash (which occupied the entire length of the line) will be pushed out, and the gap from the dasharray pattern will take its place.
And this is the gist of the whole thing: If you have a stroke that is 100px long in total, all you need is dash line and a gap, each as long as the entire stroke itself (stroke-dasharray="100 100"). Then you make one push out the other with stroke-dashoffset in an eternal battle between light and darkness, 1 and 0, to be or not to be.
Try it out
stroke-dasharray: 10 10
Hint: try maxing out everything, then reduce the offset.
Finding out the total length of a stroke
Now we know that to achieve the animation we want, we need the stroke-dasharray values and the stroke-dashoffset to be equal to the length of the stroke we want to animate.
To find out the total length of a stroke on any SVG element, you can use the
getTotalLength method, which you can access on any SVG element (but not on the
// access the line in any way possible const lineElement = document.querySelector("#thatLine"); const totalLength = lineElement.getTotalLength(); // somewhere in your HTML or template <svg> <line id="thatLine" x1="0" y1="0" x2="300" y2="150" stroke="black" stroke-dasharray="false false" stroke-dashoffset="false" style="transition: stroke-dashoffset 0.5s" /> </svg>