The State of SVG Animation

The world of SVG (Scalable Vector Graphics) is fascinating, and with everything you can do with it and all the options you have it is overwhelming.

SVG is an XML-based vector image format for two-dimensional graphics, with support for interactivity and animation. In other words, SVGs are XML tags that render shapes and graphics, and these shapes and graphics can be interacted with and animated much like HTML elements can be.

One of the frequently asked questions I get on SVG is about animating SVG images—not only the how, but the what. So let’s have a look at the current (and future) state of animating SVG, and while we’re at it, mention some tips and tools that help you do it painlessly today.

Synchronized Multimedia Integration Language , a.k.a SMIL

Pronounced “smile”, SMIL is an XML-based language that was created to enable authors to write declarative animations to create interactive multimedia presentations. These animations could then be reused to animate other XML-based languages such as HTML and SVG.

In the past as well as the recent present, SMIL has been mostly known in the web community as one of the three ways to animate SVG images.

SMIL comes with a set of animation elements that allow you to animate SVG content. Some of these elements are:

  • <animate> – which allows you to animate scalar attributes and properties over a period of time.
  • <set> – which is a convenient shorthand for animate, which is useful for assigning animation values to non-numeric attributes and properties, such as the visibility property.
  • <animateMotion> – which moves an element along a motion path.
  • <animateColor> – which modifies the color value of particular attributes or properties over time. Note that the element has been deprecated in favour of simply using the animate element to target properties that can take color values.

More elements have then been defined in SVG and more attributes added to extend the functionality of the above elements. The most important animation element defined in SVG was <animateTransform>, which you can use to animate the transformations on an SVG element—such as scale, rotation, skew, etc.

The syntax required to animate an element using SMIL is generally straightforward and human-readable. The attributes—just like the animation elements—are conveniently named so that they are also self-explanatory in most cases.

For example, the syntax to move an SVG element along a certain arbitrary path can look like this:

<animateMotion 
    xlink:href=“#circle”
    dur=“1s”
    begin=“click”
    fill=“freeze”
    path=“M0,0c3.2-3.4,18.4-0.6,23.4-0.6c5.7,0.1,10.8,0.9,16.3,2.3    c13.5,3.5,26.1,9.6,38.5,16.2c12.3,6.5,21.3,16.8,31.9,25.4c10.8,8.7,21,18.3,31.7,26.9c9.3,7.4,20.9,11.5,31.4,16.7 c13.7,6.8,26.8,9.7,41.8,9c21.4-1,40.8-3.7,61.3-10.4c10.9-3.5,18.9-11.3,28.5-17.8c5.4-3.7,10.4-6.7,14.8-11.5
    c1.9-2.1,3.7-5.5,6.5-6.5” />

And for sake of reusability, the above code can be rewritten like this:

<path id=“motionPath” d=“M0,0c3.2-3.4,18.4-0.6,23.4-0.6c5.7,0.1,10.8,0.9,16.3,2.3    c13.5,3.5,26.1,9.6,38.5,16.2c12.3,6.5,21.3,16.8,31.9,25.4c10.8,8.7,21,18.3,31.7,26.9c9.3,7.4,20.9,11.5,31.4,16.7 c13.7,6.8,26.8,9.7,41.8,9c21.4-1,40.8-3.7,61.3-10.4c10.9-3.5,18.9-11.3,28.5-17.8c5.4-3.7,10.4-6.7,14.8-11.5
    c1.9-2.1,3.7-5.5,6.5-6.5”></path> 
<animateMotion xlink:href=“#circle” dur=“1s” begin=“click” fill=“freeze”>
  <mpath xlink:href=“#motionPath” />
</animateMotion>

The difference between the second and first example is that in the second example you separate the path definition and reference it using the <mpath> element; this allows you to reference the same path in multiple <animateMotion> elements, in addition to displaying the path on the canvas, which is what we did in the second example.

The <animateMotion> element in both example could go inside an element that you want to animate, or you can specify the target of the animation using the xlink:href attribute on <animateMotion>.

You can check the live demo for the above example out here.

Motion along arbitrary paths is just one of many examples that can be created using SMIL. These native SVG animation elements can be used to create a diverse range of effects because they allow us to animate practically any animatable attribute in SVG—and this is one of SMIL’s most powerful features.

For example, using the <animate> element, you can animate an element’s color, position, dimensions, and more.

You can also use it to animate path data (the d attribute), thus allowing you to create a shape tweeting effect like the one shown in the image below.

A series of shapes morphine into one another. Image Credit: Noah Blon.

A series of shapes morphing into one another. Image Credit: Noah Blon.

The above example is one created by Noah Blon and is using SMIL to animate the path data from one shape to another. The code in Noah’s example looks like this:

<path fill=“#1EB287”>
    <animate 
             attributeName=“d” 
             dur=“1440ms” 
             repeatCount=“indefinite”
             keyTimes=“0;
                       .0625;
                       .208333333;
                       .3125;
                       .395833333;
                       .645833333;
                       .833333333;
                       1”
             calcMode=“spline” 
             keySplines=“0,0,1,1;
                         .42,0,.58,1;
                         .42,0,1,1;
                         0,0,.58,1;
                         .42,0,.58,1;
                         .42,0,.58,1;
                         .42,0,.58,1”
             values=“M 0,0 
                     C 50,0 50,0 100,0
                     100,50 100,50 100,100
                     50,100 50,100 0,100
                     0,50 0,50 0,0
                     Z;

                     M 0,0 
                     C 50,0 50,0 100,0
                     100,50 100,50 100,100
                     50,100 50,100 0,100
                     0,50 0,50 0,0
                     Z;

                     M 50,0 
                     C 75,25 75,25 100,50 
                     75,75 75,75 50,100
                     25,75 25,75 0,50
                     25,25 25,25 50,0
                     Z;

                     M 25,50 
                     C 37.5,25 37.5,25 50,0 
                     75,50 75,50 100,100
                     50,100 50,100 0,100
                     12.5,75 12.5,75 25,50
                     Z;

                     M 25,50 
                     C 37.5,25 37.5,25 50,0 
                     75,50 75,50 100,100
                     50,100 50,100 0,100
                     12.5,75 12.5,75 25,50
                     Z;

                     M 50,0
                     C 77.6,0 100,22.4 100,50 
                     100,77.6 77.6,100 50,100
                     22.4,100, 0,77.6, 0,50
                     0,22.4, 22.4,0, 50,0
                     Z;
                     
                     M 50,0
                     C 77.6,0 100,22.4 100,50 
                     100,77.6 77.6,100 50,100
                     22.4,100, 0,77.6, 0,50
                     0,22.4, 22.4,0, 50,0
                     Z;
                     
                     M 100,0 
                     C 100,50 100,50 100,100
                     50,100 50,100 0,100
                     0,50 0,50 0,0
                     50,0 50,0 100,0
                     Z;”/>
  </path>

The above code allows you to achieve an effect similar to the one in the following GIF:

tweener

You can have a look at the full code and a live demo here.

What Noah did is specify multiple path shapes inside the values attribute, and then the browser animates between these values—this is possible because these values are numerical and because they are made up of exactly the same number of points; so, practically, it is the point making the path up that are being animated.

The attribute names are almost always self-explanatory, but some of them are not. I have written an extensive article over an CSS-Tricks about SMIL, that contains everything you need to know to get started with it today—should you decide to use it. You can read the article here.

The CSS-Tricks article explains SMIL animation elements and attributes well, but if you want a comparison between SMIL syntax and CSS animation properties syntax that can help you understand SMIL better, you can check out these talk slides from a talk I gave about the topic as well.

SMIL is quite powerful and its performance great, but it was never supported by all browsers. Internet Explorer never supported SMIL—no version of it, and there is currently no intention to do so.

Moreover, SMIL has been intended to be deprecated in Blink (Chrome) as well, in favour of CSS and Web Animations, so the future does not look too bright for these animations.

Deprecating SMIL means losing the ability to animate SVGs embedded as images, without a current alternative. We will talk more about this later in the article.

Animating SVGs with CSS

You can style and animate SVG images using CSS, and animating SVG elements with CSS works almost exactly the same as it does with HTML elements, with the only difference being the type selector names and some property names.

SVG 1.1 did not require any CSS to style SVG elements, so all the styles were applied using presentation attributes. Presentation attribute examples include fill, stroke, stroke-width, opacity, etc.

The following example shows an SVG snippet that uses presentation attributes to style the “border” (stroke) and “background color” (fill) of a star-shaped polygon:

<svg xmlns=“http://www.w3.org/2000/svg” version=“1.1” width=“300px” height=“300px” viewBox=“0 0 300 300”>
  <polygon
fill = “#FF931E”
stroke = “#ED1C24”
stroke-width = “5”
points = “279.1,160.8 195.2,193.3 174.4,280.8   117.6,211.1 27.9,218.3 76.7,142.7 42.1,59.6 129.1,82.7 197.4,24.1 202.3,114 “/>
</svg>

Presentation attributes are a special kind of properties and are used to style SVG elements, and they even contribute to the style cascade in that they override inherited styles on an element, including styles specified in the user agent (e.g. browser) style sheet.

There is a long list of available presentation attributes in SVG. But what we’re interested in is the attributes that can be set and animated via CSS.

Not all presentation attributes can be set in CSS because not all attributes are available as properties in CSS. Only presentation attributes that are available as CSS properties can be set and animated in CSS. A list of all currently available presentation attributes as CSS properties can be found in the SVG 1.1 specification here.

So, if we were to go back to the previous code example and turn the presentation attributes into CSS properties, we can rewrite the code as follows:

<svg xmlns=“http://www.w3.org/2000/svg” version=“1.1” style=“width: 300px; height: 300px;” viewBox=“0 0 300 300”>
<polygon
  style = “fill: #FF931E; stroke: #ED1C24; stroke-width: 5;”
  points = “279.1,160.8 195.2,193.3 174.4,280.8   117.6,211.1 27.9,218.3 76.7,142.7 42.1,59.6 129.1,82.7 197.4,24.1 202.3,114 “/>
</svg>

The styles can also be moved out into their own <style> “island”, just like HTML styles can be. Now, in the above example, if the width and height were set on a <rect> element inside the SVG, we wouldn’t have been able to set those attributes in CSS on the <rect> element because it’s still not possible.

In the new SVG 2 specification, the list of SVG styling properties is extended to include more properties such as content size and geometry properties including—but not limited to—x, y, width, height, cx, cy, r, and more. The new list can be found in the SVG 2 specification here.

Note that some of these properties are already available in Chrome, so you can test them in that browser if you want.

It only makes sense that if some properties can be set in CSS and their values are animatable then the properties can also be animated in CSS, and thus the SVG elements these properties are applied to can also be animated via CSS…

CSS Transitions and Animations on SVG Elements

Indeed, you can apply CSS animations and transitions to the animatable SVG properties in CSS. This allows you to create nice hover interactions such as changing the fill color of an icon, for example, and more complex animations such as transformations in both the second and third dimensions.

For example, to change the fill color of an SVG icon on hover using CSS, you would do it just as you might expect, like so:

.icon—twitter {
    fill: #eee;
}
.icon—twitter:hover {
    fill: #55ACEE;
}

As a matter of fact, CSS is perfect for simple animations and interactions like hover interactions, and it also generally performs very well, though not in all browsers, since CSS animations on SVG elements are currently not hard-ware accelerated in all browsers, so performance can be better—and hopefully will improve in the future.

Moreover, note that CSS animations (using @keyframe, for example) do not work in IE9 and below.

CSS Transforms on SVG Elements

The most impressive kinds of effects usually include some kind of transformation animation that either rotates, scales, skews, or simply translates an element. A simple example using transformation animations is the following set of weather icons also created by Noah Blon and available on Codepen.

See the Pen SVG Icons Animated with CSS by Noah Blon (@noahblon) on CodePen.

Some of the icons translate a group of shapes (e.g. the rain drops) from their initial position “in the cloud” downwards, infinitely, others use a rotation transformation to rotate the sun about itself, etc.

Now, if you are viewing the above demo in Firefox, you will notice that some of the animations are broken. There is a reason for that.

Animating SVG elements using CSS is very similar to animating HTML elements with CSS, with one major difference when it comes to transformations: by default, the initial default transform origin of an HTML element is (50%, 50%), which is the element’s center. By contrast, an SVG element’s transform origin is positioned at the origin of the current user coordinate system, which is the (0, 0) point in the top-left corner of the canvas.

So, suppose we have an HTML <div> and an SVG <rect> element:

<!DOCTYPE html>
…
<div style=“width: 100px; height: 100px; background-color: orange”> </div>
<svg style=“width: 150px; height: 150px; background-color: #eee”>
  <rect width=“100” height=“100” x=“25” y=“25” fill=“orange” />
</svg>

If were were to rotate both of them by 45 degrees, without changing the default transform origin, we would get the following result (the red circle indicates the position of the transform origin):

initial-to

So, if you want to animate an SVG element around its own center, you need to explicitly set the transform origin using the transform-origin property.

rect {
  transform-origin: 50% 50%;
}

Changing the transform origin on the SVG element like that would give you the following result:

set-to

That being said, this does not currently work in Firefox. It is a known bug.

Noah’s demo uses percentage values to set the transform origin to be the center of the animated elements, and this is why it is broken in Firefox. The way to make a rotation work in Firefox as you would expect it to is to use absolute values (pixels, ems, etc.) to set the transform origin. And when you do that, the origin will be specified relative to the SVG canvas’ user current coordinate system. For example, if you specify 50px 50px as a transform origin, it will be the point at 50px 50px from the top left corner of the SVG, not relative to the element itself.

In most cases, this is not how you want to set a transform origin, but it is necessary at the time being to make it work in Firefox.

In addition to the problem in Firefox, IE and Opera have a problem which is that they do not honor CSS transforms at all on SVG elements. And there are quite a few more issues that we will mention in a later section in the article.

Much more complex animation effects can be created by animating SVG using CSS, but these effects mostly rely on transformations to look great, and CSS transformations are currently limited, buggy and inconsistent across browsers.

However, you can do more with CSS than simply transition colors or transform elements…

SVG Line Drawing Effect with CSS

One of the most impressive and popular SVG animation effects is the line drawing effect. An example of the line drawing effect was first seen on the Xbox website and is explained in this article on the Vox media blog. The animation can be seen in the following recording:

xbox

This effect is created by animating two specific SVG properties—namely stroke-dasharray and stroke-dashoffset. The first property allows you to turn your solid line “border” (stroke) into a dashed line, by specifying the length of the dashes and spaces in between them, and the second property allows you to change the offset—that is, the position at which these dashes start along the path’s line length. Both of these properties are available in CSS and are animatable.

By turning the path you have at hand into one long dash and then animating the offset of that dash along the path, you can mimic a line drawing effect using nothing but CSS and an SVG path.

This effect was first explained by Jake Archibald in this article over on his blog. The article also included an interactive demo that explained how this technique works. The following is a recording using that demo to show the effect of the two properties:

line-drawing-demo

You can play with the demo yourself in Jake’s article.

The trick behind this technique is to know the exact length of the path so you can turn it into one dash of that same length, and then use that same length as an offset value to “pull” the dash outside the visible boundaries of the path (backwards), and then animate it back in.

The formula to create this effect in CSS thus looks like so:

#path {
    stroke-dasharray: pathLength;
    stroke-dashoffset: pathLength;
    /* transition stroke-dashoffset */
    transition: stroke-dashoffset 2s linear;
}

svg:hover #path{
    stroke-dashoffset: 0;
}

This line drawing effect is very effective in creating more expressive UI elements. You can see a whole lot of examples using this technique to improve common UI elements and interactions on Codrops. A couple of examples are:

Now, in a lot of cases, you may not know the exact length of the path you want to animate, and if you have many paths you’re animating, it can become tedious to know and then set and animate the length for each one. This is where a JavaScript solution is a better option.

In fact, JavaScript enables you to overcome many of CSS and SMIL’s animation limitations, especially when it comes to animation timing and synchronization capabilities…

Animating SVGs with JavaScript

Using JavaScript to animate SVGs, you get the same capabilities you would get with SMIL and CSS, and more. There is only one limitation I can think of when you use JS to animate SVGs—we will talk more about that in the next section.

If we were to get back to the last example in the previous section where we created the line drawing animation using CSS, we can do the same thing using JavaScript, and thanks to the SVG DOM method getTotalLength(), we can always know the length of the path we’re working on by simply selecting that path and using this method to retrieve that value:

var path = document.querySelector(‘.drawing-path’);
path.getTotalLength();
//set CSS properties up
path.style.strokeDasharray = length;
path.style.strokeDashoffset = length;
//set transition up
path.style.transition = ‘stroke-dashoffset 2s ease-in-out’;
// animate
path.style.strokeDashoffset = ‘0’;

In most cases, and unless the animation is very simple, you will want to use JavaScript to create this effect. Some plugins that help you do this already exist—example here and here; the latter is a plugin for the very popular animation library: Greensock.

If you animate SVGs using vanilla JavaScript from scratch, you will still face some of the browser inconsistencies and bugs mentioned earlier. Some of the available SVG animation libraries can help you avoid that because they take care of all of this for you.

There are many SVG animation libraries out there; the three most popular ones are: Greensock, Snap.svg and Velocity.js. I’m sure that if you work with SVG animations, you can think of a couple more (for example, D3.js), but these are the three most popular ones today.

Using JavaScript, you can animate SVG path data (d attribute) too. This allows you to create some really impressive animations that can literally take your animations and UIs to the next level.

For example, the following recording shows an effect created by Codrops’s Manoela Ilic, which recreates Mac OS X’s genie effect by animating the shape of a path (the lime green area):

genie-sm

Even more creative effects can be created that can improve upon the general user experience of a user interface by leveraging proper animation effects to help hint the user on the whereabouts of elements, in addition to creating more realistic interface effects.

You can also use JavaScript to create simple transitions and animations that you can do in CSS, but without the browser bugs. Greensock, for example, provides you with a cross-browser way to do so, because it takes care of providing the appropriate technique to create those animations in Internet Explorer, for example, by falling back to SVG attribute animations instead of CSS property animations which are not supported in IE.

The Web Animations API—a JavaScript animation API—is meant to fill in the gap for some (if not all) of the functionality that SMIL provided—and that is fantastic, but it still will be limited in the case where the SVG is embedded as an image. Read along for details.

SMIL vs CSS vs JavaScript

The current and future state of browser support for SMIL is the main reason why I neither use it nor recommend using it anymore today. Unless the state of support changes so that more browsers support is, not less, then I don’t see this changing any time soon, and I expect SMIL usage to drop even more in the future.

As for CSS, it can only animate so many SVG properties, not all of them. Attributes such as the data attribute d of a path cannot be animated in CSS—at least not yet. So no shape tweeting effects can be established using CSS at the time being, or any other path animation effects for the matter.

Not to mention that Internet Explorer up to version 11 did not support CSS animations and transitions on SVG elements, and the new MS Edge browser still does not support CSS transformations on SVG elements. All this and the transform origin bug in Firefox along with a lot of browser inconsistencies when animating SVG with CSS are a reason why I only recommend using CSS for simple, possibly trivial animations that are not vital to the functionality of whatever you’re working on. If the animation is crucial to the image, page or application, I certainly recommend using JavaScript.

Note: Jack Doyle wrote an extensive article on CSS-Tricks explaining the browser bugs and inconsistencies when it comes to applying CSS transformations to SVG elements. You can read the article here.

All that being said, CSS is already getting more capabilities that spawn from SVG SMIL animations. Today, we have a CSS Motion Path Module which imports SMIL’s motion along a path capability into CSS, so we can animate SVG and HTML elements along paths using nothing but CSS. The Web Animations API previously included this functionality, but it was later on removed with the introduction of the CSS Motion Path Module.

However, with SMIL being deprecated, CSS is going to need more than the motion path module to fill in the gaps, because we still can’t animate SVG paths in CSS, and CSS also does not let you sequence and group animations so they play perfectly together. SMIL’s animation triggering and synchronisation capabilities are superb, and CSS still comes short in this aspect.

This is why JavaScript is currently my go-to tool for animating SVG, and my library of choice is Greensock. Greensock has a lot of features that focus on SVG animations, and allow you to write and create SVG animations without having to worry about browser inconsistencies. Greensock also adds more to the animation methods and properties so you can create animations that behave just as you would expect them to, by working around some non-intuitive default animation behaviour in SVG.

Snap.svg is the go-to library for SVG manipulation and is known as the jQuery is SVG, but Greensock’s timeline feature and other features it has makes it more powerful when it comes to creating complex SVG animations.

That being said, JS comes with one major limitation when animating SVG: an SVG embedded as an image—using <img>, <picture> or a CSS background image—cannot be animated using JavaScript, for security reasons.

What does this mean? It means that if your SVG is embedded as an image, any JavaScript animations you define on it will not work. Only CSS and SMIL animations work, and the former need to be defined inside of the <svg>, not externally. Interactions (such as :hover) will not work either way.

SMIL allows us to create complex path animations and have them work in SVGs embedded as images; but SMIL is going to be deprecated, and CSS does not yet have this ability, so we need to wait till CSS gets more features to fill in SMIL’s shoes; until then, animating an SVG as an image will be very limited.

Mozilla’s Brian Birtles has written an article where he discusses the most common use cases of SMIL, and lists some features that CSS needs to getting order to fill in the gap created by SMIL’s deprecation. But until then, you can either use SMIL and drop support for IE and Chrome in your images, or simply settle for simple animations using CSS, or use JavaScript to create awesome effects and embed your SVG in one of the other possible embedding techniques.

In addition to what each animation technique can or cannot do, you can read more about how each of them performs in this excellent article by Sarah Drasner, where she weighs the different animation techniques with benchmarks, comparing CSS, SMIL and a couple of JavaScript animation libraries. Make sure you check the article out for details.

Final Words

SVG is a big world, with a lot of options and a lot of developments and changes happening on an almost daily basis. You need to weigh your options and your needs, and pick the technique that works best for you—from the creation stage, to optimization, to embedding and finally animation. I hope this article helped give you an overview of what’s currently possible and not possible in the world of SVG animation, hopefully making it easier for you to choose the appropriate animation technique for your next project. I certainly did not cover every aspect of this topic, but hopefully enough to help you make a better choice when choosing an SVG animation tool today.

Thank you for reading. 🙂

Get Started

Free TrialInspired by what you've read? Kick off your next project with Dreamweaver. It's part of Creative Cloud. Download a trial for free!

Share your thoughts

Your email address will not be published. Required fields are marked *

*