Animating SVG is a bit unique in that there are three distinctly different ways you can approach animating it.
1. Animating with CSS @keyframes
SVG elements can be targeted and styled with CSS. Meaning, you can apply animation through @keyframes. Like this:
<svg viewBox="0 0 127.9 178.4">
<path id="left-leg" d="M37.6,138.8c0 ... " />
</svg>
.left-leg {
fill: orange;
animation: dance 2s infinite alternate;
}
@keyframes dance {
100% {
transform: rotate(3deg);
}
}
You might choose animating this way if…
- The animation is fairly simple.
- You only need to animate properties that CSS can animate.
- You already know and are comfortable with CSS animations.
2. Animating with SMIL
There is a syntax for animations built right into SVG. Here’s a very simple example:
<svg viewBox="0 0 127.9 178.4">
<path d="M37.6,138.8c0 ... ">
<animate attributeName="fill" dur="5000ms" to="#f06d06" fill="freeze" />
</path>
</svg>
Here’s a big tutorial on all that is SMIL.
You might choose animating this way if…
- You need to animate properties that CSS can’t, like the shape itself.
- You need other SMIL specific features, like beginning an animation when another ends without manually syncing durations/delays. Or interaction stuff, like beginning an animation on a click.
3. Animating with JavaScript
With JavaScript, you have access to things like requestAnimationFrame (or other loops), so you can animate just by way of rapidly changing property values. There are also frameworks out there for working with SVG that typically have animation stuff built in. Or animation frameworks that work with SVG. Like SnapSVG, GreenSock, SVG.js, or Velocity.js.
Here’s an example with SnapSVG:
<svg id="robot" viewBox="0 0 127.9 178.4">
<circle id="left-pupil" cx="34.4" cy="15.4" r="4.8" />
</svg>
var s = Snap("#robot");
var leftPupil = s.select("#left-pupil");
leftPupil.animate({
r: 50,
fill: "lightgreen"
}, 1000);
You might choose animating this way if…
- You’re working in JavaScript anyway, perhaps your animation has to do with data you receive with JSON or the like.
- You need JavaScript anyway, because you need the logic or math or something else really only possible there.
- You’re interested in the JavaScript solving some bugs for you.
- The scope of your animation is rather large/complicated and you need the abstraction and organization JavaScript can provide.
Demo
See the Pen Three Ways to Animate SVG by Chris Coyier (@chriscoyier) on CodePen.
Doesn’t how you ultimately use the SVG affect your options?
It does. If you’re using SVG-as-<img>, you won’t be able to use use CSS animations from another stylesheet. But, you’re SMIL animations will work, in some browsers (at the time of this writing, Chrome yes, Firefox no). I wouldn’t be surprised if embedded CSS in SVG files work or will work one day. JavaScript, probably not.
If you’re using SVG in a CSS background-image, I imagine it’s a similar story as above.
If you use inline <svg>
, all the possibilities are open to you.
If you’re using SVG through an object
or iframe
, you would need to embed the scripts/styles right in the SVG for it to work.
Awesome stuff! Thanks!
Hi,
I just tried to recreate this code within my WordPress website, and I am able to get the JavaScript working, but I’d really like to be able to use the CSS animation. I cannot get that to work at all. I copied all of the CSS and the SVG from the example. In WP, I also remove all of the line breaks from the SVG file. The file itself shows up fine, but the CSS is not working. Any ideas??
Thank you!
Edit: I got the working and not the JS. I also am using Chrome. I checked it in FireFox and Safari and it is not working with CSS in either of them. I also tried with !important on all of the CSS and that didn’t help. I’m not that familiar with @keyframes. Maybe I need to add another step for WP?
Here is my CSS:
You have to prefix your keyframes too:
That did it! Thank you!!!!
Hi Clare . can you do it in css
Another reason for using JS animations would be IE support, it’s the only way that works. Also the reasons listed for SMIL apply to JS as well.
Thanks for sharing Chris.
Here’s an SVG animation (Google Chrome experiment) I did using Greensock.
https://ihatetomatoes.net/svg-christmas/
I think it’s currently the best tool for more complex timelines.
I hope we’ll see SVGs transform-origin with percentage values implemented more consistent across the browsers. That seems to be the missing piece.
ihatetomatoes, did you compare it to snap.svg? Thoughts? Thanks for sharing your animation. Must have been quite a few lines of code there ;-]
@Rob – I’ll be honest I haven’t looked at snap.svg in a lot of detail, I’m sure it’s great and useful library.
There is also a plugin which makes Snap.svg including polygon and path shape tweening to work with Greensock, but again I haven’t tried it yet, just found it now.
Hey Peter, looks like you’re xmas animation got featured in css-weekly (you probably already know..but if not now you do).
Plans to do a “code walk through” and/or is the code available for perusal? Having done a bunch of snap.svg animations recently I’m really curious what your code looked like for something that’s a bit more complicated (mine are simple 3 or 4 step sequences, whereas yours is defintely closer to a realistic ad campaign [in terms of number of sequences/sophistication]).
@ihatetomatoes Argh, apologies ^Peter^Petr
Thanks for the update Rob, I didn’t know about the css-weekly mention.
I will be deconstructing the page in my future articles on websitedeconstructions.com and my blog.
In the meantime here is a simplified Codepen demo with some of the GreenSock timelines.
Can you share some of your snap.svg animations?
Thanks Petr. Wow, that .to chaining syntax is definitely quite nice. I’ve been meaning to write a sequence method, but I might make a .to instead :)
I made a deferAnimation which allowed me to start one animation mid-way of another..it’s just a wrapper around setTimeout: https://github.com/adobe-webplatform/Snap.svg/issues/335
My experiments are sort of similar to some of the codedrops ones, and I’m writing a tutorial but it won’t be for a bit (especially with holidays coming up and all). If I get a spare cycle to throw up a pen I’ll come back and drop it here. In meantime (just so you see how potentially verbose the code is), here’s an animation for toggling between a hamburger icon to and ‘X’ where I hide the middle rectangle and just morph the paths (warning: ugliness follows!):
Syntactically,
loadSvg
is my own custom helper that just sets up the constructor stuff (48 is just for my0 0 48 48
viewBox). The two libs (greensock / snap.svg) seem to have familiar if not fairly similar interfaces (I was able to read your codepen pretty comfortably). Nice to know there’s some nice lib options to choose from!Just looked at your app.min.js using prettyprint chrome (until my eyes got dizzy lol) and I definitely need to practice fully utilizing the transform origin! I did some of this making eyeballs look to each side, but I love the way your effects look by messing around with that. Very neat. Fwiw, I don’t have this big background doing Flash/AS3 so I’ve very much been learning to think in animation sequences. Curious, do you have a past in Flash or animations?
No wonder your eyes got dizzy, the code is uglified which makes all variables
a, b, c
etc.I did study multimedia and did a bit of Flash/AS, but that’s almost 10 years ago. Since then all I’ve been doing for living is front-end work (CSS/HTML/JS).
And animations? You just need to play around with things and see what feels natural.
Yah, that’s what I’ve been doing, a tweak here, a tweak there. It’s pretty exciting what this stuff can do. Well, I’ll wait to read your article re what your findings were browser by browser for the transform-origin with percentage values issues.
I’m definitely inspired to do a more full-blown animation sequence to kick off 2015 but I’ve gotta finish up my “simpler” tuts first hehe. So many interesting things to look into ex. your code has peeked my interest to do a double implementation in snap.svg|velocity|tweenmax just to see the differences. Thanks for the inspiration Petr and looking forward to see what else you come up with.
Back on topic for the 3 ways to animate svg, I’d personally love to see more examples like Petr’s pulled off with SMIL but it just seems like it would be ridiculously impractical to try to do this sort of thing declaratively. Seems better for simpler animations. Plus the support issue makes it hard for me to get super motivated to perfect or dive deep in to SMIL – jm2c (maybe I’ll be convinced otherwise)
Hi Chris! Watched this and it was a nice intro comparison between CSS vs. SMIL vs. JS. I’ve read but yet to play with SMIL so it was particularly useful to see your SMIL tinkering here.
You know me, the “gotcha guy” wink wink. There are two that come to mind:
For my experiments, I’ve noticed that I seem to have much more success using snap.svg when I just go ahead and “make compound path” on all primitive shapes. I spent so long trying to animate polygon points, for example, and got frustrated and just went with a path and it work in minutes (I realize snap.svg supports animating polygon points, so probably “user error” of some kind, but it was very hard to find working examples that matched what I was trying to do).
I mention 2., because, at first watching, it looked like you might have done the same (convert primitives to paths). Confirmed?
Thanks for the vid tut Chris!
Hi Chris, in your video you´re showing us an exported SVG robot with a cool markup semantics output, are you using an Illustrator script or some extension to make that?
Nice tutorial as usual
I just snagged some robot vectors off of Shutterstock, I think. I keep a subscription there because I often need little bits of stock photos / vectors, but they aren’t a sponsor or anything, just a business expense.
Hi,
Is there any way that anyone can think of to make a simple eyelid opening and closing? Like the circle, only with angles at the sides. I couldn’t do a straight line. It’d have to be a curved line that changes from up to down. Any ideas? This may be too complicated to try, but I figured I’d try to figure it out.
It would be kind of like this:http://codepen.io/chrisdivina/pen/yBpsr, only with one lid moving from top to bottom instead of two lids closing in the center.
Hi, I am told that google chrome will no longer support SMIL. It’s because no one was really using it. I would counter that until svg became a “thing” (within the last year) there was no reason to use SMIL. But now that svg IS a thing, now is not the time to drop support for it.
…
<path id=”left-leg” ..
in css:
.left-leg must be #left-leg
…
[ illegal selector!]
Awesome intro. Thanks!
Hi
im a newbie and i want to add the code to my wordpress..how do i go about that in my dashboard?Thanks
With bl-js :
https://codepen.io/bl-js/full/zEXMYM/
Very cool! thanks for the tutorial :)
I’m trying to make some paths being “drawn” and changing their color on the way, but i can’t find a way of doing that. Elements can be drawn animating their
stroke-dashoffset
, but then they can’t be seen when the animation starts…So is the only way to achieve this to have two paths in the svg and animating only one of them?
thanks for the suggestions! :)