From our sponsor: Meco is a distraction-free space for reading and discovering newsletters, separate from the inbox.
SVG has been one of the most underused technologies when it comes to web development. Despite it’s usefulness and powerful possibilities it’s still a mystery to many and when it comes to integrating it and using animations, many developers don’t know where to start. With great libraries like Snap.svg the use of SVG assets becomes more easy and today we’d like to explore how to animate SVG icons.
You’ve surely seen some great examples of animated icons using CSS transitions and animations like the Navicon Transformicons by Bennett Feely which were explained in this excellent collaborative tutorial by Sara Soueidan. We want to try to do something similar using SVG icons with the help of Snap.svg.
Please note that we are working with a modern JavaScript library for manipulating our SVGs. Older and non-supporting browsers will not be capable of all features.
The first thing we do is to create some SVG icons using an SVG editor like Inkscape. We used a size of 64×64 pixel for the icons.
For each icon we want a special animation to happen. For example, for the zoom icon we’ll want to scale up the plus path. We’ll define what will happen for each icon in our script.
We’ll add the icons dynamically to our page using Snap.svg and if SVG is not supported we’ll simply show a background image for the span elements that we use to wrap each graphic:
<section class="si-icons"> <span class="si-icon si-icon-play" data-icon-name="play"></span> <span class="si-icon si-icon-monitor" data-icon-name="monitor"></span> <!-- ... --> </section>
With the help of Modernizr we can define the fallback in our CSS:
.no-svg .si-icon-play { background-image: url('../png/play.png') } .no-svg .si-icon-monitor { background-image: url('../png/monitor.png') }
The PNG icons were generated with the fabulous iconizr tool. You could as well use CSS sprites and define a active class but we decided to just do a very simple fallback for this demo.
If you add the class “si-icon-reverse” to the span, the icon will be initially rendered with the reversed “shape”. For instance, if you want to display the stop icon rather than the play icon, you can achieve that in the following way:
<span class="si-icon si-icon-reverse" data-icon-name="play"></span>
Tiny break: 📬 Want to stay up to date with frontend and trends in web design? Subscribe and get our Collective newsletter twice a tweek.
Now let’s take a look at what we are doing in the JavaScript. The idea is to do something with each icon. That can be some kind of transformation, like a rotation or a scale, or a change of a path altogether. With the Snap.svg we can dynamically load our SVGs, which we store in a folder, and manipulate them in a very practical way thanks to the powerful API.
The configuration variable for the icons, “svgIconConfig” has all the animation settings for each icon.
Let’s take a look at its logic:
[icon name - same name given to the data-icon-name] : { url : [url of the svg file], animation : [array of animation configs for each element] }
Each animation config can have the following structure:
{ el : [element selector], animProperties : [animation config for the initial/from and final/to state] }
Let’s take a look at some possible values for the initial and final state:
from : { val : [animation name value pairs], after : [attribute name value pairs to be applied when the animation ends], before : [attribute name value pairs to be applied before the animation starts], delayFactor : [animation delay factor], animAfter : [animation name value pairs to be applied when the animation ends] }
A real example would be the following:
myIconName : { url : 'svgs/myIconName.svg', animation : [ { el : 'path:nth-child(5)', animProperties : { from : { val : '{"path" : "m 61.693118,24.434001 -59.386236,0 29.692524,19.897984 z"}', animAfter : '{"stroke" : "#000"}' }, to : { val : '{"path" : "m 61.693118,24.434001 -59.386236,0 29.692524,-19.7269617 z"}', animAfter : '{"stroke" : "#444"}' } } }, { el : 'rect:nth-child(3)', animProperties : { from : { val : '{"transform" : "t0 0"}', after : '{ "opacity" : 0 }' }, to : { val : '{"transform" : "t-10 -10"}', before : '{ "opacity" : 1 }' } } } ] }
You can initialize the icons like this:
new svgIcon( element, configuration [, options] );
And these are the possible options:
{ speed : 200, // animation speed easing : mina.linear, // animation esing evtoggle : 'click', // event: click || mouseover size : { w : 64, h : 64 }, // size onLoad : function() { return false; }, // callback on svg load onToggle : function() { return false; } // callback on toggle (click or mouseover/mouseout) }
Check out the demo to see some examples for different sizes, easings and activations (on click and on hover).
We hope you enjoy this experiment and find it useful!
First 😀 Is good to see the use of SNAP this fast after it came out. lovely as always.
Really helpfull. Thanks for sharing.
Been wanting to start experimenting with Snap.svg since it got out, but I am one of those devs u mentioned that don’t know where to start with SVG. Thanks for writing this, ML. =) and thanks for linking to my article ^^
Cool … it’s amazing .. thanks
Hi, I really enjoyed the animations for some of these, especially the ones with different easings, very cool and app like.
One question though, I’m new to using svg. Just curious how you got those values you input for the starting and endpoints for the animation?
Thanks!
Hi Chris,
thanks a lot for your feedback! This is how I did it: the starting configuration is basically the same as what’s in the SVG file. For the transforms I simply played with the values and chose something that fits (e.g. rotate or translate the element(s) ). For the path morphing, I drew the end result in the SVG editor and copied the resulting path to the end state. Hope it makes sense. Cheers, ML
Whoa, i love SVG so much, and you can manipulate it into cool animations
So cool!
Love your icons! Simple way to make a page more attractive.
I can’t stop playing with them!
Hi Mary, wonderful experiment as always, but I didn’t understand how the mouseover works. When does Snap trigger the “animation”?
Hi Davide, I’m not sure what exactly you mean.. The mouseover/mouseout works in the same way like the click. In both cases the event is bound to the span. You can specify which one you want in the options of our script like this:
new svgIcon( elem, { evtoggle : 'mouseover' } );
Let me know if this answers your question. Cheers, ML.
AMAZING WORK!
Thx It’s Very Nice 🙂 !
Bad value X-UA-Compatible for attribute http-equiv on element
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
Great tutorial! Thanks for encouraging people to use SVG and giving iconizr a mention! 🙂
Really cool! Was surprised to see it working great with android stock browser (on Jelly Bean). I’ll surely give it a try for my next html5 mobile app.
Great tutorials, as always!
This article and the demo is incredible. Thanks for the shoutout Mary Lou!
What a great work Mary. Amazing thought of animating icons.
Nice work! How do I change the color of the icon following your demo examples?
Works brilliant! Many thanks for your work.
Wow! just wow!
It’s one of the most visually impressive things you’ve ever done. Great job!
Cool animation and effective use of SVG.
[btw: SVG has the Oscar for THE most underused technology]
Just one question: why not use the animation feature already present in SVG?
Sebastian
Really Amazing work 🙂
Thank you so much Helping me a lot
Great! Thank you!
Very nice one. Thank you!
Hi Mary,
Thank you for amazing tutorial as always 🙂
I’m trying to add this animated icons to the buttons. But I still can’t make SVG buttons animated when I make mouse over the button (not icon). Could you please tell me is it possible?
The only way I found is to add styles for buttons directly to the with icon. But in this case the caption goes before icon and I can’t make an icon floating to the left side of button.
Thank you very much in advance! 🙂
Very nice tutorial
Great article!
I’ve used your scripts and created a new set of animated SVG icons. The Snap.js is so great. Please check this icon set and tell me what do you think: http://nethusiastic.com/demo/animated-svg-icons/
Thanks 🙂
Hi Zoltan. Icons themselves look nice but you script must be pretty bugged as when you hoverin/out really for few seconds on any of the icons they stop to respond. I hope my comment will help you to improve
Is there a problem with the source files in chrome. ive downloaded the source files, which open / appear / animate fine in both safari and firefox, but do not appear/ animate in chrome? please help.
Version 30.0.1599.101
Scott
This is the errors that shows in the chrome console for every icon: No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘null’ is therefore not allowed access.
how were you able to fix the ‘null’ issue?
Might you have to download all resource in local instead of loading from other site. I think your trouble in Cross-domain issue.
Guys I’m getting so exited about Snap. Nice tuts Mary Lou and Zoltan! for me, as a not seasoned JS-guy, the Snap-API docs are really hard to understand. That what made not trying to use Raphael. These examples are great. I’m going to play with them!
Thanks for this amazing tutorial! I have a quick question on triggering the animation. It looks like using “evtoggle”, I’m limited only to “hover” and “mouseover”. Is there a way to trigger the animation using anything else? For example, if I hover on a separate element?
Hi Mike, you could do something like this:
Let me know if that works for you.
Cheers, ML
Is it possible for anyone to include a working example of the animation of one element being triggered by hovering or clicking on another element? That seems like something that would be handy to be able to do and I can’t seem to get it to work.
Hey Mike,
Where you ever able to figure this out? I’m trying to implement a similar solution.
Following Mary Lou’s suggestion, I had success with the following (using jQuery, but I’m sure it wouldn’t be too hard to re-write in native JS), where the icon is inside
.diagram-header
. Clicking this ancestor element triggers the animation.$(el).closest('.diagram-header').click(function() { svgicon.toggle (true); });
Hi Mary,
Awesome tutorial. This tutorial inspired me to to start learning about svgs and snap. I am trying to do create an icon but I get an
‘Cannot call method ‘appendChild’ of null ‘ error
I can’t tell if the problem is with my svgConfig object or my constructor. Can you please help. Here is the
jsbin link
Hi Raju, try wrapping the inner contents of the svg element in a <g>. My fault, I forgot to mention it :S Let me know if it works. Cheers, ML.
Awesome Mary, works like a breeze. Thanks a lot. 😀
Mary Lou, could you give us that exact code bit that shows how to “”wrap the inner contents”. I’m new to this. That would really really help me. Thanks a lot in advance!
Great stuff! Did you know it ‘breaks’ when you franticly keep hovering the icons? 😉
I am so sorry to find out that this does not work at all on Chrome (31.0.1650.63, the latest version for MacOSX)..There is nothing appear on my screen except green background and text. However, on Safari, everything is OK.
Works fine here with the same version.. Any errors shown in the console? Thanks.
Hi, I threw all files into the server then everything work well, I think Chrome has some problem with local files(format like: file:///…….)
Thanks 🙂
very good
Hi Mary,
I’m loving your site, only came across it the other day but have been truly inspired!
I am playing around with these icons and I was wondering, is there a way of remotely triggering the animations, say from an anchor?
Thanks 🙂
hi
thank you for the great article
do you know how can i add demos to the wordpress theme?
Mary Lou, You guys are killing it with all these great tutorials! This is another great one.
Hi Mary Lou, thanks for a great article and demo! In order to minimize http-requests, would there be a way to modify this so you can read all icons from the same SVG?
Excellent work!
I found your article while googling for “animated svg”, as I am trying to make an animated logo for my web page.
Thak you!
Very good work! I’m using this on my website and I’m trying to combine it with your very cool overlay navigation effect! Do you think it’s possible to do this?
Nice work!
Is it possible to scale the icons by percent of the viewport so they will get bigger/smaller when you change the viewport size? I thinking of something like this:
<body> <div style="width:10%"> <!-- svg icon here, scaled to 100% of the surrounding div and thus, to 10% of the viewport width --> </div> </body>
hey, i make the download, but when i open the project, i can’t see no items, i don’t know what happen! help me!
got it to work? i have the same problem…
Hi there,
first of all thx for the great work. Trying to animate a single icon on my personal website I ran in some issues. As I am far away from being a JS pro I think your scripts in the demo focusses on having multiple animated icons in a website. Till now I am unable to transform your code to make it work for one single icon/element.
Would love to get some help on this.
thx
David
Omg I love this. <3
good
Wow!
This article gave me courage to look into snap svg!
thanks you
my share: instead of external loading svg, one can include a sprite once and than get the icons element by Id localy.
When I open the source of this project and open the index.html I don’t see any icons. Do anybody know why?
I’ve got the same problem. It says “Uncaught TypeError: Cannot read property ‘type’ of null ” on the SVGs.
It doesn’t work with local links, open with virtual server.
Love this SVG tutorial!
Is that possible to have 2 events – like when hover on a hamburger, it expanded, but when it click, it cross. But it is the same SVG. How to achieve this? Could you provide an example? Thank you so much~~
How can I change the color from white to black for the icons?
Replace this to the callback-function of Snap.load() in
svgicons.js
(around line 75):self.svg.append( g );
with this
self.svg.append( g ); var paths = g.selectAll("path"); paths.forEach(function(p){ if(p.attr('fill') != 'none'){ p.attr({fill: self.options.color}); } if(p.attr('stroke') != 'none'){ p.attr({stroke: self.options.borderColor}); } });
and update your default options in
svgicons.js
(around line 72) to thissvgIcon.prototype.options = { speed : 200, easing : mina.linear, evtoggle : 'click', // click || mouseover size : { w : 64, h : 64 }, onLoad : function() { return false; }, onToggle : function() { return false; }, color: '#000000', borderColor: '#ffffff' };
you can now use
color for background color and
borderColor for the stroke color of your icons
Awesome!!!
Finally got it working! If you letting it run locally and not on an external server under Windows you have to enable IIS under “Control Panel\Programs\Programs and Features” then click on “Turn Windows features on or off” and tick “Internet Information Services”. After that windows search “IIS” and open the application. Then under you Computer’s name (upper left hand side) und “Sites”, rightclick and “add website”. there define a name, path to your folder on your PC and define a hostname, e.g. “myicons.localhost”. access that hostname in your browser, e violà, the icons are being displayed now. It all has to do with JS being prevented locally from running due to a general risk of running malicious SW.
Thanks for your help; I would never guess it had to do with the IIS configuration.
Hi thanks very much for this tutorial. I am very new to SVG and I am just not sure if I am missing something. What are the possible values inside the val? Such as: ‘{“transform” : “r0 32 32”}’, what does that r mean?
basically what are r, s and t? Any reference documents?
Sorry, but I find these animations very jarring, especially the one that goes from the “Menu” button into an “X”. It’s the same click with two different meanings.