Diving deep into SVG animations

The Optimizely mobile team went heads down in October to publicly launch our redesigned mobile product. We improved stability, streamlined customer onboarding, and added requested features.

I worked with our designers to implement three animated graphics to supplement the new product. The animations led me down a road full of research, cross-browser inconsistencies, and three animation technologies. The journey taught me about diving deep into a new technology. I’d like to share some of those lessons with you now.

Initial research on animation principles and technical guides

jQuery unleashed web animations to the masses with their easy-to-implement functions and interest in CSS animation has sky-rocketed in the past two years. This ease-of-use makes it tempting to implement flashy animations that serve no benefit to the user.

Hoping to avoid that trap, I read up on the 12 basic principles of animation and Google’s material design animation guidelines. I discussed possible animations with fellow designers and searched online for technical guides.

I discovered a few great resources in the process. I’ve listed these in the “Resources” section below.

Lesson learned: Spend time researching before diving into a project involving unfamiliar and quickly evolving technologies. Break the project into small parts and try to estimate the amount of time and potential roadblocks for each. My initial design research was helpful to build an animation that subtly enhances the user’s experience, but I wish I had spent more time costing the development.

Deciding on an approach: JavaScript, CSS, or SMIL?

As it turns out, there are many ways to animate SVGs. Chris Coyier of CSS-Tricks does a great job explaining the three common approaches, but this is a quick overview:

  • JavaScript libraries such as Snap.svg, svg.js, and Velocity.js remove many cross-browser inconsistencies and are great for complicated animations. Update (Sept. 2, 2015): Many readers have pointed out that I should add GSAP to the list.
  • SMIL, a set of HTML elements used for SVG animations, is very powerful but doesn’t work in Internet Explorer. It was also recently announced that Chrome will be phasing out support.
  • CSS keyframes are easy to work with and have good browser support but aren’t as powerful as JavaScript or SMIL.

I took this information and narrowed down my options. The lack of Internet Explorer support and grim future eventually eliminated SMIL. I didn’t want to introduce another JavaScript library into our large codebase for such a small project, so that eliminated JavaScript. CSS keyframes are great for their ease of implementation, so I settled on them.

Lesson learned: No approach is perfect and they all have different trade-offs to evaluate. Pick the one that has the most benefit and fewest drawbacks for your use case, and be equally open to all techniques rather than getting stuck on one before fully understanding all options.

Discovering CSS animation browser bugs and inconsistencies

Opting to animate the SVGs using CSS instead of JavaScript uncovered a whole slew of cross-browser inconsistencies. (CSS-Tricks, once again, has a great article explaining some of these inconsistencies.)

Unfortunately, I didn’t notice these bugs until diving deep into each animation.

  • The SDK detection animation cross-browser issues, for example, surfaced in Safari when I started animating two properties at the same time.
  • Various components of the SDK connection gesture animation appeared out-of-sync once I sent a CodePen link to co-workers. At the time, I was implementing the animation using SMIL and CSS. I never saw the timing issues because the CSS was cached on my machine. (I eventually tried to implement the entire animation in SMIL which led to a more legitimate browser bug.)

These bugs led me down deep rabbit holes as I tried other approaches. Eventually, the issues I ran into were specific enough that Google and StackOverflow were no longer useful and debugging required reading parts of the W3C specifications to see if the browser implementations were incorrect.

I ultimately filed two browser bugs: one for Webkit, and one for Firefox.

Lesson learned: Spend less time prematurely polishing a project. It’s important to uncover the technical hurdles as quickly as possible.

Working around the bugs

Hofstadter’s Law: It always takes longer than you expect, even when you take into account Hofstadter’s Law. (Douglas Hofstadter)

It took three large rewrites to make the connection gesture animation work. That animation is complicated because the hand and white circular path are separate and are animated using different techniques.

First iteration (CSS and SMIL): It is hard to animate an element along a path in CSS, but SMIL makes it easy. On the other hand, it is easy to create line animations in CSS, but hard in SMIL.

I tried to combine both technologies in my first attempt, but failed since, as previously mentioned, CSS and SMIL started executing at different times. This made both animations out-of-sync.

Second iteration (Only SMIL): The hand was animating nicely with SMIL, so I tried implementing both in SMIL. I scratched this approach when I found a bug in Firefox. Plus, it wouldn’t work in IE and I didn’t want to find an IE specific solution.

Third iteration (Only CSS with some math): The final approach, albeit hacky, was to write a JavaScript function that generated N number of coordinates along an ellipse. I then plugged each coordinate into a keyframe and used CSS transforms to move the hand along the ellipse.

I eventually converted the JavaScript function to a Sass mixin and implemented the white line animation in CSS as I did in the first iteration.

A CSS-only approach meant that I had to remove easing and a more complex hand movement from the animation, but I was glad to make those compromises to move on.

I’ll spare the details, but it’s worth noting that each animation required similar design compromises.

Lesson learned: It’s important to iterate quickly on a project based on technical limitations, feedback from designers, and the end goal. There will be roadblocks which may include some compromises for the sake of time or what is technically feasible. Work closely with designers to address these challenges. (This is why our UI Engineers are part of the design team.)

What would I have done differently?

There are two things I would do differently if I implemented this again:

  • Explore JavaScript animation libraries: Many of the issues I ran into could have been avoided if I decided to implement the animations with JavaScript. I’m still not sure if it would be worth increasing the JavaScript bundle size for three small animations, but perhaps it would have encouraged us to experiment more with animation in future projects.
  • Performance profiling: Google has placed a huge emphasis on improving performance in Chrome. This has led to the development of excellent tools to measure the performance impact of an animation. I should have spent more time researching this and understanding the impact of each animation.

Despite my early mistakes, this was an incredibly rewarding project.

I encourage you to also jump on the opportunity to explore a subject you are interested in but unfamiliar with. The trial and error is time-consuming, but the lessons learned are valuable and can be applied to any projects.


Resources for easing and animation ideas

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.