Published on 9 Sep 2025
SVG Animations
There are several ways to animate SVGs:
- JavaScript.
- SVG animations level 2 (formerly known as SMIL).
- CSS animations and transitions.
This article covers SVG animations level 2 spec.
What is SVG Animations Level 2?
It is a modern specification, based on SMIL.
See SVG animations spec for details.
It adds new tags for animating elements:
<animate />
for animating any property.<animateTransform />
for animating transformations.<animateMotion />
for moving shape along a path.<set />
to set property.<discard />
to discard parent element.
Example of using <animate />
to change stroke-dashoffset
:
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"> <g fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" > <path d="M12 3l9 17h-18l9 -17Z" stroke-dasharray="64" stroke-dashoffset="64" > <animate attributeName="stroke-dashoffset" values="64;0" dur="0.6s" fill="freeze" /> </path> <path d="M12 10v4" stroke-dasharray="6" stroke-dashoffset="6"> <animate attributeName="stroke-dashoffset" values="6;0" begin="0.6s" dur="0.2s" fill="freeze" /> </path> <path d="M12 17v0.01" stroke-dasharray="2" stroke-dashoffset="2"> <animate attributeName="stroke-dashoffset" values="2;0" begin="0.8s" dur="0.2s" fill="freeze" /> </path> </g></svg>
Click icon to restart animation.
Many developers confuse it with a deprecated old SMIL animations spec It is not SMIL, it is similar new spec, which reuses some ideas from old SMIL spec.
Pros and cons
Pros:
- No JavaScript required, no third party libraries, no dependencies!
- Easy to use.
- Can be used in external images: background images, mask images, images added with
<img />
tag (see issues below).
Cons:
- Cannot conditionally disable animations, for example if browser has
prefers-reduced-motion
option set. - Rather limited set of options, hard to trigger animations without JavaScript.
- Uses more CPU than identical CSS animations.
What can be animated?
There are several commonly used animations:
- Animating
stroke-dashoffset
property of shapes that use stroke. This gives a nice effect of shape being drawn. - Animating shape coordinates. This is rather complex to implement, but can be very powerful.
- Animating presentational attributes: colors, opacity, stroke width. This is very simple to implement, but not really interesting.
- Animating transformations, such as rotating or scaling shapes.
Examples of icon animating stroke-dashoffset
, d
property of <path />
and fill-opacity
on render:
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"> <g fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" > <path d="M11 9h6v10h-6.5l-2 -2h-2.5v-6.5l1.5 -1.5Z" fill="currentColor" fill-opacity="0" stroke-dasharray="48" stroke-dashoffset="48" > <animate attributeName="fill-opacity" values="0;0.3" begin="1.3s" dur="0.15s" fill="freeze" /> <animate attributeName="stroke-dashoffset" values="48;0" dur="0.6s" fill="freeze" /> </path> <path d="M17 13h0v-3h0v8h0v-3h0z" fill="currentColor" fill-opacity="0" opacity="0" > <animate attributeName="d" values="M17 13h0v-3h0v8h0v-3h0z;M17 13h4v-3h1v8h-1v-3h-4z" begin="0.6s" dur="0.2s" fill="freeze" /> <set attributeName="fill-opacity" to="1" begin="0.8s" fill="freeze" /> <set attributeName="opacity" to="1" begin="0.6s" fill="freeze" /> </path> <path d="M6 14h0M6 11v6" opacity="0"> <animate attributeName="d" values="M6 14h0M6 11v6;M6 14h-4M2 11v6" begin="0.8s" dur="0.2s" fill="freeze" /> <set attributeName="opacity" to="1" begin="0.8s" fill="freeze" /> </path> <path d="M11 9v0M8 9h6" opacity="0"> <animate attributeName="d" values="M11 9v0M8 9h6;M11 9v-4M8 5h6" begin="1s" dur="0.2s" fill="freeze" /> <set attributeName="opacity" to="1" begin="1s" fill="freeze" /> </path> </g></svg>
Click icon to restart animation.
Performance
Animations are not equal. Some require more CPU power, some less.
High CPU usage because of expensive animation calculations can result in user closing page. Nobody wants that.
Avoid animations that do not have finite duration, such as constantly animated shapes.
This is why I’m not a fan of icons constantly moving for no reason. Those icons use CPU, while distracting from content. I prefer animating rendering icon and transitions between icon states - those animations are ran for limited time and do not affect performance.
Stroke animation
It is a very simple and elegant animaiton, does not use a lot of CPU.
It works by setting stroke-dasharray
to value just above length of shape (to account for rounding differences between browsers)
and animating stroke-dashoffset
from same value as stroke-dasharray
to 0.
<path d="M4.22 4.22c-4.29 4.3 -4.29 11.26 0 15.56" stroke-dasharray="20" stroke-dashoffset="20"> <animate attributeName="stroke-dashoffset" values="20;0" begin="0.7s" dur="0.2s" fill="freeze" /></path>
How to get length of a shape?
You can use getTotalLength
method of shapes: MDN docs.
- Assign unique ID to element you want to get length of:
id="test1"
. - Open SVG in browser.
- Open browser console.
- Run command to get that element and get
getTotalLength()
result
document.getElementById('test1').getTotalLength();
You can test it on this page. An engine icon sample above has a path with id set to “test1”.
Material Line Icons
When I have started experimenting with SVG animations few years ago, I have created a Material Line Icons icon set.
Links:
It is open source.
You can browse icons to see how animations are implemented.
Isses with SVG animations
While SVG animations spec is exciting, it is not without problems.
There are several issues:
- Timing can be difficult to control.
- Need to make sure all IDs are unique.
- There are no timing functions, such as
animation-timing-function
in CSS. - No conditional animations, such as checking for
prefers-reduced-motion
option. - Long and complex animations can use a lot of CPU. Avoid long animations.
Timing
The biggest problem is controlling animation timing.
For example, in Material Line Icons animations are supposed to start when icon is rendered, so it should be as simple as just rendering icon, right?
It depends on how icon is rendered.
Embedding SVG in HTML
If icon is embedded in HTML, animation timer starts when icon is first rendered and DOM has fully loaded.
Requirement of DOM being fully loaded means a small background script, like website tracker, can prevent animations from running.
Usually this is not an issue, so embedding SVG in HTML is the easiest way to control timing.
Additionally, you can control icon animation timing using new methods added to SVG element:
setCurrentTime()
to set timing. If you set value to 0, animation restarts.pauseAnimations()
andunpauseAnimations()
to pause/resume animations. Useful to avoid animating icons that aren’t visible, reducing CPU load.
Using SVG in CSS
If icon is used as background or mask image in CSS, controlling animation timing is impossible.
Furthermore, timing can be broken.
It would be logical for animation timing to start when element with icon as background image is first rendered, but that is not always the case.
When animation timer does not make sense:
- If another element with same icon was rendered, timer has already started.
- If icon is loaded from browser cache (page previously displayed), timer is broken.
That makes animated icons in CSS almost unusable.
There is a solution, but it requires JavaScript and works in specific conditions: if you assign an icon as background or mask image in inline style, just add something for cache busting to URL. For external images it can be a parameter. For data URLs you can embed HTML comment with random text.
Unique IDs
Developers usually just paste SVG in documents without thinking.
SVG can contain IDs for elements like:
- Masks, clip paths, reusable symbols.
- IDs assigned to shapes to control animation sequences.
All IDs are supposed to be unique.
If there are multiple elements with the same ID, browser uses first element it finds, which could be an element from another icon.
So watch for IDs, make sure they are unique.
In Iconify Utils I have added a function to replace IDs, which is used in Iconify icon components: replaceIDs documentation.
Deeper dive
This is a short introduction article meant to:
- Give basic knowledge of how SVG animations work.
- Explain how to animate stroke.
If you want to learn more, check out SVG animations spec. It explains each animation tag in details and has many examples.