The following is a guest post by Sarah Drasner (@sarah_edo). Sarah has been researching and giving talks about animation lately. I jumped at the chance to have her share some of that research here, this time focusing on SVG animation and the different tech choices you can make to do it.
After working with a number of SVG animation techniques for a few months now, I can give you a basic overview so you can compare them yourself. There are good reasons to use each one of these methods. Hopefully this post can point you to the right tool for the job.
We’ll go through a basic comparison of features. Then we’ll dig into how well they perform. Two different benchmarks are included. One is from recordings off the Chrome DevTools timeline, and the other is measuring visual recordings from the screen.
While HTML elements styled with CSS tend to perform better in animation, SVG has the advantage of being able to draw anything while being resolution independant. In the benchmarks, we’re specifically working with SVG images.
We’ll be comparing these SVG animation techniques:
There are countless others that we don’t cover, including Snap.svg and the older Raphaël.
High Level Comparisons
- It has good performance, especially when hardware accelerated, but perhaps not as good as the DevTools timeline reports. We’ll touch on that later.
- It’s easy to integrate in existing UI, as you don’t need to load any other resources.
- CSS is perfect for small interactions like hover states.
- There are some good resources for more finely-tailored cubic-bezier easing, which makes it easy to visualize the potential outcome while developing.
- There are some backwards compatibility problems. @keyframes will not work on IE9 or lower.
- You can only create user interaction on pseudo state such as
- Chaining multiple animations is done with delays, which work well for simpler animations. For longer animations, this makes the workflow very complicated. It is difficult to adjust timescales, especially if you need to manipulate the first few frames.
- Physics can be cumbersome. Complicated tasks like friction, or a progressive decreasing bouncing ball are extremely complex at best and not an option at worst.
transform-originfor SVG is not consistent:
- Stacking transforms one after another is not intuitive, as it responds to the last placement of the element.
- It does not show consistent behavior from browser to browser.
- Easy to use syntax. If you have existing jQuery animations, it’s easy to change them over to Velocity because it has the same style syntax. If you are used to
$.velocityis easy to work with.
- There are many out-of-the-box easings, and spring physics is available. For further refinements there is also step-easing where you can pass an array.
- The syntax is more concise than CSS or SMIL.
- You can stagger multiple animations with one line of code, particularly if you use the UI plugin available.
- Deeper browser support than CSS.
- Performs much better than existing jQuery
.animate()but not as well as CSS, SMIL, or GSAP.
- Offers backwards compatibility back to IE8, but not as far back as GSAP.
- Easy to use and the most compact syntax.
- The timeline for GSAP allows you to easily control and manipulate sequenced animation; this makes longer animations dramatically simpler to work with than pretty much any other technique. (You can set multiple tweens at the same point in time, create scenes, and move backwards and forwards, at different timescales- basically animate your animations).
- Automatically hardware accelerated. Performance is extremely good — as good as native rendering.
- Applying physics is simple. They have an ease visualizer that’s pretty helpful.
- Has a solution to some known
- Offers support back to IE6. Better support than CSS, SMIL, or Velocity.
- GreenSock has a robust feature set. If you need to do something, GSAP has probably thought about it. To get a sense of what I’m saying, check out this robust plugins page, https://greensock.com/plugins/ most of which are included in the TweenMax version (though if you’re worried about filesize, they have a lean, stripped down TweenLite version). There are some specialized features such as animating along a path (like SMIL can do with
<animateMotion>), drag/drop interactions, and even working with canvas.
- They have a jQuery plugin that will override the existing jQuery
.animate()and enhance performance with no extra coding necessary.
- Their code is open source, but you might need a license for commercial use in certain situations.
- Has a straightforward declarative syntax.
- You can morph paths and shapes using the same syntax with which it was written, which makes it very intuitive. This is nice for things like logos or morphing button icons.
- You can animate along a path.
- Performs very well, arguably better than CSS, Velocity, and GSAP in terms of visual display.
- There is non-delay based chaining like beginning an animation when another ends.
- Easy to add to existing SVG syntax and no need to load external resources.
- There is some speculation on whether support for SMIL will continue. Chrome is possibly introducing it into the Web Animations API (along with everything else), but if this doesn’t go through it might not be well-maintained as it is currently underused.
- Chained animations are fairly limited.
- There is currently no support for IE.
In case IE browser support is a primary concern, here is a very simple breakdown:
There are a number of considerations when constructing a balanced benchmark across animation approaches. It needed to be a very simple SVG — I’ve used a rectangle with a stroke. Additionally, it needed to loop so that variations in performance over time could be observed. The benchmarking code can be found on GitHub, and also in this collection on CodePen.
Before you begin animating an SVG with any technique, it is best to optimize the SVG, just as you would with any other image. A couple of nice options are the in-browser SVG Editor or the node-based SVGO.
This is the hardware accelerated CSS version:
See the Pen Benchmarking SVG Animation – CSS hardware accelerated by Sarah Drasner (@sdras) on CodePen.
There are two different benchmarks included in this: one based on the Chrome DevTools timeline recordings, and one based on visual recordings off of the screen. This dual approach is necessary as Chrome may not be accurately reporting all processing in the timeline. Jack Doyle of GSAP does a good job of showing possible underreporting in this video.
Since the way that animations will be impacted will largely be the audience’s interpretation of it’s visual display, I’ve included a visual recording of the “jank” that can occur when running each along with the Chrome DevTools Timeline benchmarks. Jank is the amount of visual stutter that occurs when creating an animation or scroll event with the goal being silky smooth animations. If you would like to read more on this, JankFree is a great resource for tools and tips for optimizing your code.
Not All Demos are Created Equal – Hardware Acceleration and CPU
It’s important in these comparisons to realize that simply building the animation with each method doesn’t tell the whole story. With each technique, there are ways to hardware accelerate the animation to increase performance. In this demo, each technique is accelerated natively to the type of animation. For example, it is possible to optimize SMIL by giving the element its own layer in the compositor with CSS (e.g.
transform: translateZ(0)). But instead, I’ve shown how to do so directly inside SMIL. To demonstrate the performance delta, I’ve also left in a non-hardware-accelerated example of CSS and SMIL.
All code that was built from a library was proofed and approved by the library’s author prior to testing.
How to hardware accelerate with CSS
- Setting transforms to null, and then moving them with transforms.
- You’re offloading them to the GPU (Graphics Processing Unit). Most modern browsers ship with hardware acceleration, but don’t use it until they are told they need to.
- Other GPU acceleration:
perspective: 1000;– keeps the animation from flickering.
- Isolate the layer you need to move or adjust.
- Move with transforms.
How to hardware accelerate with SMIL
<animate>and set x, y, z values (with 0 for z).
- Similar to CSS, this moves the element off to its own layer. Moving with transforms performs better than margins or top, left because it doesn’t repaint.
How to hardware accelerate with Velocity
- Move with
translateY. Set the element to
- Make sure to avoid layout thrashing by declaring a variable for elements that you animate more than once to prevent multiple lookups (not applicable here but worth mentioning).
How to hardware accelerate with GSAP
- In the demo we set the element to
force3D: "true", but GSAP now ships with this automatically in place. This means you don’t have to use
translateZ: 0;to hardware accelerate, it’s already included.
- Moving objects with X and Y perform better than margins.
- TweenLite is the lighter-weight version of GSAP, and it’s recommended to use this for smaller animations. TweenMax offers support for loops, so we use it here.
A word to the wise: hardware accelerating too many layers at once can have an inverse effect. Each layer is a mapped GPU texture — having an excessive number will quickly exhaust available resources. Thus, it’s important to use hardware-acceleration judiciously.
Here are the results from the timeline benchmarking: (the smaller bars indicate better performance.) Pay particular attention to “painting”, as this is the most costly of the events. Each benchmark was run 5 times to ensure consistency, then averaged. Included here is a version of CSS that is hardware accelerated (HA), and also where it is not (naive), to illustrate how significantly performance can be affected. These tests were run on Chrome Version 40.0.2214.91 (64-bit) — the latest stable release as of the article publication date. Please keep in mind that the version number can alter the timeline reporting.
Important Things to Note
Opacity and transform tend to perform better overall, and timeline reports them as being much better in hardware accelerated CSS:
Because of the aforementioned possibility of underreporting for CSS animations, it’s important to weigh things not purely based on the timeline, but also what you see visually, as that is how the audience is going to evaluate the animation.
In order to see the full story, I also conducted a few benchmarks based on what was happening visually. To do so, I took a screencast of the first full iteration of the loop in each technique, and then used a tool called Physmo to plot every movement of the SVG element. I mapped a comparison of any time the rate of change did not advance visually for more than 2 frames. This shows the amount of time that the animation would appear paused, therefore the jank. Here is how each technique stacked up:
As you can see, just as Jack’s demonstration showed, optimized CSS did not actually outperform every other technique in terms of visual display. SMIL had the most consistent rate of change, then GSAP followed. GSAP, CSS, and Velocity performed in a relatively similar range compared to what the timeline reported, which was that they were far different.
Please keep in mind that the screencast technology could feasibly alter the results here. I encourage you to play with the demos I made or, better yet, write your own comparisons to see how the techniques stack up.
Benchmarks vary depending on the context. Working with a different set of parameters, especially while loading other resources could affect these results. An ongoing dialog surrounding performance under different circumstances is vital for improving technologies in animation.
More Complex Animations
This is all well and good for short animations, but what is it like building a longer, more complex animation? GSAP allows you to work in an adjustable timeline, or many timelines — all of which you can adjust the timescale of, change placement in order, and even overlap. CSS does not allow you to overlap different transforms at once, which, for very realistic motion, ends up being a big deal. If you think about how someone moves, or how objects interact with each other, there are very rarely events when everything works in one linear chain without overlap.
In CSS animation you can chain events with delays, but what happens when you want to adjust one part of it, and it has corresponding parts? You then have to retrace your steps through the whole process of building and redo the math for everything that follows. GSAP’s timeline gives you much more control for manipulating these. They also allow for things like physics, which can be instrumental for realistic animation.
SMIL is great for things like a morphing SVG, which none of the other techniques offer at the same capacity. However, it is yet unclear whether the spec will be maintained over time, and because you have to use existing points, it makes less sense to use this technique for many disparate elements at a time.
CSS is wonderful for things like transitions of page elements. Things you see more often on a corporate website where the goal is not to show off animation, but rather smaller effects to add interest or emphasize changes. If you need a tiny bit of interaction, hover effects and lightweight scrolling libraries such as Waypoints can be an easy way to do so.
Animation libraries like GSAP and Velocity are great to use in production because the upkeep and the amount of code necessary is much smaller. Velocity might not perform as well as the others, but the simple fact that you can change your existing jQuery code to something more performant with one word is a huge boon. Velocity also offers physics, which CSS does not. GSAP takes it all one step further: you can take existing jQuery and simply add the GSAP jQuery plugin. It will override your existing jQuery and make it all perform more efficiently without you having to change any code. GSAP also has physics, motion along a path, you name it.
Because of some serious performance failings, jQuery on it’s own should no longer be considered an appropriate way of animating things.
Recommendations for use:
- Use CSS animations for small transitions or simple animations. You need not load another resource, and small transforms on hover can be a boon for interaction and UX. Particularly when you don’t need physics or to do a lot of stacking SVG transforms, which are not always necessary.
- Use SMIL for morphing SVGs into one another in the case of logos, etc., and when the thing being animated can fallback to a stagnant image in IE.
- Use Velocity for a performance boost on existing jQuery animations without having to change a lot of code.
- Use GSAP for highly performant animations or longer-scale animations that have multiple scenes. It solves major issues with browser-to-browser consistency for SVG transform origin. GSAP is very robust with a broad feature-set, but you can use smaller versions without a lot of bells and whistles, loading only what is necessary.
Everyone has their own preferences, and it is impossible to be completely unbiased. It’s important to be purposeful in our selection of tools, as they all have specific tradeoffs, and context matters within a development environment. This post serves as a general comparison to help point developers to the most appropriate technique for what they are setting out to accomplish.
Fantastic writeup, Sarah!
A few notes:
Animating along a path is also not going to remain a SMIL advantage as CSS now has a Motion Path module which should hopefully find its way to implementation this year.
CSS transforms are not hardware accelerated on SVGs—at least not in webkit-based browsers. Firefox does offer better performance in this regard, afaik.
Very well done on the article, Sarah. The benchmarks are incredibly useful and insightful.
Thank you, Sara! I’m a huge fan of your work.
First, about morphing shapes- true- I’ve made an edit to the post above.
The CSS Motion Path Module is very interesting- do you have any idea when that might be coming out and whether or not it will have an effect on SMIL support for motion along a path (or in general) in the future?
Lastly, using null Z transforms on the whole SVG element seemed to have an effect in the timeline benchmarks- I did not run a visual comparison of CSS naive, and CSS HA, which might be useful. I’d love to read more on your findings, I’m sure you have great information on it that I might have missed. If you’d like to pass it along, that would be very helpful!
Thanks, Sara, I appreciate it.
Last time I spoke to Dirk, the Motion Path spec editor, he said that we should start seeing it in browsers this year—but this was a few months ago, so I hope this still holds.
I’m not sure how it will affect SMIL. I know that it affected the Web Animations API in that the object used for creating motion along a path was removed from the API, in favor of the CSS specification.
I love SMIL, but rumor says it will be pulled out of blink, IE is not considering putting any effort into it—the Web Animations API takes priority here, and Firefox does have some bugs. So I’d personally not use it except for simple animations that are not crucial for the image I am using.
Again, really well-written and informative work, Sarah. =)
That’s all really useful information. And thanks, Sara!
Great writeup of different techniques. Thanks!
Hey Sarah, really enjoyed this roundup. Couple of things I thought I’d mention:
We don’t support compositing in SVG in Chrome (AFAIK). For example, in your SMIL demo, if you go to DevTools and hit the Rendering tab, you can switch on “composited layer borders” and you’ll see that the box doesn’t get an orange border around it like any other promoted element. If you switch on “paint rectangles” you’ll see it goes light green indicating that it’s been painted every frame.
If you want a complete picture of properties mapping to layout, paint and composite I made CSS Triggers for all the funsies.
Benchmarks are so difficult, I think, because if they’re simple they don’t necessarily suffer from main thread congestion (which is what normally causes issues on animations that aren’t entirely compositor-centric, like a keyframed transform animation), but if they’re too complex they become very zoned in on one use-case and it’s hard to draw meaningful comparisons.
I’m really surprised that the GSAP and Velocity values differ all that much. I would have expected that they’d do roughly the same DOM manipulations and would incur similar penalties in style, layout, paint and composite.
I love that you’ve done some benchmarking here, and I hope others will do the same, not just for SVG but for all manner of things! :)
In the last paragraph I try to address context a little bit- it’s true that whatever you’re working with in your own development environment will affect how things perform as well. The idea is to help people be a little purposeful in their decisions and hopefully branch out from just one way of working.
Your CSS Triggers site is great! I’ll definitely be playing with that all day today. Thanks for your insights.
Great info. I’d really like to see the benchmarks (particularly the screencase jank calculation) done on other browsers, to see whether the same patterns hold true.
Firefox SVG animation performance has significantly improved in the past year, but I don’t know whether the improvement just reflects overall faster SVG rendering or whether it is caused by specifically optimizing declarative animations. On the other side, Safari is probably lagging a bit behind Chrome in terms of performance optimization.
Finally, an important clarification:
Internet Explorer does not currently support CSS animations/transitions when applied to SVG style properties. Nor do they support CSS transforms of SVG elements. So CSS animation of SVG is pretty limited, even in IE 10 and 11. You can animate font-size, but that’s about it.
I think it’s a great idea to do visual benchmarking from browser to browser- I’ll probably do that next. (Though if others are curious and want to tackle it, too, the more information the better)
Good point about IE- the browser comparison I showed was not particular to SVG, just the animation techniques themselves and you are absolutely right that that’s confusing- I’ll make an edit to clarify that.
Thanks for your insight, I really enjoyed your SVG article here as well.
Heyo! Author of Velocity.js here.
I truly appreciate comprehensive breakdowns like these that go beyond mere speculation and actually take deep-dives.
I haven’t optimized Velocity for SVG animation beyond a workflow perspective; it doesn’t surprise me that its SVG animation performance is off from GSAP. Velocity’s focus has been on standard HTML elements since its goal is to drastically improve the most popular typical UI animation use cases (as opposed to graphical SVG animation).
However, I will drastically tweak performance since there are some low-hanging fruit I can pick off over the course of an upcoming weekend.
It’s unfortunate that the improvements won’t later be reflected in this article, but that’s life :-)
Thanks for your continued feedback on the benchmarks. I’m of course happy to rerun them with your improvements as I did previously- just let me know when it’s ready and I can add an addendum to the article. :)
Benchmarks for Front-End will always be a bit of a moving target. Things will continuously be updated, which is actually a boon for all of us. I’m excited to keep this conversation going and have other benchmarks be included as well.
Thanks for all your hard work on performance improvements for our community.
Anyway you could benchmark against jQuery’s regular animate?
Yes, that’s a good call. There’s a lot of literature about the performance boost you can get with any one of these techniques, but I can include it just to show that precisely. I’ll write some for jquery as well and update the article. Likewise, you can also submit a pull request to the repo yourself if you like, or fork one of the pens in the codepen collection. All of the code is open-source so that it can be improved upon. Thanks!
You say that GSAP is “open source” but it doesn’t seem to be. It’s free to use in many situations, and requires payment in others (when you sell access to your site that uses it). But this kind of “free” isn’t open source.
GSAP is indeed open source in the sense that the source code is freely available for download and it’s on github, wide open for everyone to see. It’s also completely free to use for almost every type of usage. But I totally see your point. “Open source” means different things to different people. GSAP’s licensing model is aimed at making it extremely accessible (free even for most commercial projects) while protecting it from the most common killer of most open source projects: stagnation. Carl and I have worked full-time for years supporting and refining it. Biased as I may be (and I totally am), I’d argue that GSAP’s license is a feature, not a liability. The proof is in the pudding. It’s not for everyone, though. Your clarification is a totally valid one. Thanks for offering it.
Jack, you mentioned several times the pitfall of “stagnation” for open source projects, but I have to say that this take on it strikes me as self serving. Apache, Jquery, Firefox, PHP, etc–have these stagnated? What about the proprietary IE6, ActiveScript, and Flash?
Your GSAP product looks quite good, but it is not open source, by any definition that I’m aware of. I’m not allowed to fork the code, right? Obviously the license is your choice, but I’m unconvinced that your choice will ultimately make it “stagnation-free.” And if you do stagnate (go out of business, lose interest, focus in a direction that doesn’t interest some of your users), where does that leave me? Rather than hacking your stuff to make it not stagnate, I’d have to find something else.
Great post. Didn’t realise css was underreporting until now.
Why don’t you cover snap.svg again? It’s like one of the biggest player and too important to be left out.
Hi Hawk Phil,
Snap.svg is indeed important. As of yet I haven’t worked with it extensively enough to feel comfortable drawing conclusions about it, so it is omitted for the time being. I will probably rerun a different kind of benchmark in the coming months, and it will be included at that time. However, if you would like to add it in this round, you can submit a PR or fork one of the pens- the code is open source for just such a reason, and I’d be happy to run tests on your contribution. Thanks!