CSS

How to Animate SVG paths with CSS

Last Updated Wednesday, 6 January 2021

On a recent tutorial, I created a bunch of checkboxes, and one of those had a smooth line animation:

And this can all be done with CSS. The SVG element looks like this:

html Copy
<svg id="one" width="10em" height="10em" viewBox="115 140 70 70"> <path fill="none" stroke-linecap="round" class="path" stroke="white" stroke-width="4" d="M173 196 L172 196.33333333333334 L169.8 197.2 L164.71428571428572 197.71428571428572 L161.5 197.875 L156.125 198 L150 197.625 L143.5 196.75 L136.75 195.125 L130.875 192.75 L125.75 189.875 L121.875 186.25 L119.125 181.875 L118.125 176.875 L118.625 171.875 L120.375 167 L123.25 162.5 L127.125 158.625 L131.875 155.25 L137.5 152.625 L143.5 151.125 L149.5 151.125 L155.5 152.375 L161.25 154.5 L166.5 157.5 L171 161.125 L174.75 165.375 L177.625 170.25 L180 175.125 L181.375 179.625 L181.875 183.625 L181.5 187.25 L180.75 190.375 L179.5 193 L178 195 L176.375 196.375 L174.75 197.375 L173.375 198.125 L172 198.83333333333334 L171 199 L170.5 199"></path> </svg>

And the CSS is like this:

css Copy
svg { stroke-dasharray: 1000; stroke-dashoffset: 1000; pointer-events: none; } #one { animation: firstAnimation 2s linear forwards infinite; } @keyframes firstAnimation { to { stroke-dashoffset: 0; } }

So how does it work? stroke-dasharray refers to the width of the dash and the white part of the line, and stroke-dashoffset refers to the starting point of the dash. So when we set both to 1000, our starting point is 1000, which is beyond the end of our line, and then the dash is 1000 units long, more than the line length.

When we animate the dashoffset to 0, the dash moves back up the line, resulting in the line becoming visible again. If we wanted this to only run once, we just have to remove the infinite indicator on the CSS animation line.

Different offsets

To illustrate this better, here it is with a dasharray of 10, and a dashoffset of 0:

And with a dashoffset of 10:

And finally, with a dashoffset and dasharray of 50, with then a varied animation process:

Here is the CSS code for that:

css Copy
svg { animation: secondAnimation 2s linear forwards infinite; } @keyframes secondAnimation { 0% { stroke-dasharray: 20; stroke-dashoffset: 20; } 30% { stroke-dasharray: 20; stroke-dashoffset: 200; } 50% { stroke-dasharray: 60; stroke-dashoffset: 400; } 80% { stroke-dasharray: 30; stroke-dashoffset: 200; } 100% { stroke-dasharray: 20; stroke-dashoffset: 20; } }