How to animate a loading screen with Snap.svg & SMIL

Paul Thomas, senior front-end developer at Green Chameleon, describes an SVG animation technique with fallbacks


Paul Thomas, senior front-end developer at Green Chameleon, describes an SVG animation technique with fallbacks


Introduce the effect

We are going to examine the loading effect as used on This will be achieved using any SMIL-supported browsers other than IE, for which we’ll create a fallback using Snap.svg ( The live demo and full code can be found at

So why use SMIL?

The benefit of using SMIL (Synchronized Multimedia Integration Language) is that you don’t need to download heavyweight JavaScript files. You can use them in symbols (eg icons) although this only seems to be supported in Chrome. Please note, for the sake of brevity CSS vendor prefixes have been left out.

Create the SVG

Create the SVG in your editor of choice, in this case we’ve used Inkscape ( Convert the ‘type’ into a ‘path’ without embedding the font and combine the paths so that a single path is a whole word, and not a single letter. Embed as a plain SVG into your HTML so we can manipulate it with CSS and JavaScript:

001 <div class="flex-container">     002 <svg viewBox="0 0 400 55"id="loading">
003 <path id="loading-path" d="m ..."/>
004 </svg>    
005 </div>    

Setting the stage

We’ve embedded the SVG and added a simple layout. There’s a background image with ‘background-size: cover;’ and the loader is placed in the centre of the stage using the .flex-container <div>. The SVG is set to take up 20% of the screen width, but this is variable:

001 body {    
002 position: relative;    
003 background-size: cover;
004 background-position: 50% 0;
005 background-repeat: no-repeat;    006 background-image: url(bg.jpg);    007 }    
008 .flex-container{    
009 width: 100%;        
010 height: 100vh;    
011 display: flex;    
012 justify-content: center; 
013 align-items: center;
014 background: rgba(#fff, 0.3);    015 }
016 #loading{
017 display: block;            018 width: 20%;    
019 height: auto;
020 }

Create the Snap.svg version

We are creating a gradient that is a single colour (R189, G189, B189) but has three stops with opacity (0, 1, 0) respectively. Make the gradient move by animating the direction (x1, x2) from between: x1=-1, x2=0 to x1=1, x2=2. This starts the gradient off the path to the left, and moves it through off the path to the right, so it disappears, while maintaining its proportions:

001 var loading = Snap.            select('#loading');     
002 var gradient = loading.gradient('l(0, 0, 1, 0)rgba        
003 (189,189,189,0):0%-
004 loading.attr({fill: gradient });    
005 var animGrad = function(){     
006 gradient.attr({ x1: -1, y1: 0, x2:     0, y2: 0 });    
007 gradient.animate({ x1: 1, y1: 0,     x2: 2, y2: 0 }, 1500,            
008 mina.linear, animGrad);        
009 };    
010 animGrad();

Create the SMIL version

Make a static gradient for animating in SMIL. This is the same gradient we applied in the Snap.svg version, but using <defs> directly in the SVG itself. Add the SMIL animation by animating the same x1 and x2 values directly in the SVG:

001 <defs>     
002 <linearGradient id="gradient"     x1="0" y1="0" x2="1" y2="0">         
003 <stop offset="0%" style="stop-    color:rgb(255,255,255); stop-opacity:0" />
004 <stop offset="50%" style="stop-    color:rgb(255,255,255); stop-opacity:1" />             
005 <stop offset="100%" style="stop-    color:rgb(255,255,255); stop-opacity:0" />
006 <animate attributeName="x1"     dur="1500ms" values="-1; 1;"     repeatCount="indefinite" />
007 <animate attributeName="x2"     dur="1500ms" values="0; 2;"         repeatCount="indefinite" />
008 </linearGradient>            009 </defs>

Toggle JavaScript or SMIL

Don’t run the JavaScript if you can use SMIL – use Modernizr to detect for SMIL support and if it’s not found, run JavaScript. Use a loader like Require.js to download the Snap.svg library if SMIL isn’t supported, saving unnecessary download where SMIL’s supported:

001 if(! Modernizr.smil ){         
002 /* all JavaScript from previous steps goes here */
003 } else {
004 /* fill the svg path with our SMILanimated gradient */    
005 $('#loading').attr('fill', 'url(#gradient)');    

006 }