The Ultimate Email CSS Animation Guide: Part 2


Welcome to part two of our CSS in email breakdown. If you missed the first blog make sure to check out part one here.

So far we’ve covered what CSS animations actually are, the pros and cons of using them over animated GIFs, considerations before using them, and we looked at some clever examples of CSS animation in email. So, now, we’ll dive right into part two.

A more in depth look at CSS animations

Let’s look at what CSS animations really are. By using CSS we can add animation to most HTML elements without using common web practices such as JavaScript or Flash. What that means for us email developers is that we can use it as an enhancement for email clients that support CSS.

So, what can we actually do? We’ll cover each of these points more thoroughly later in the blog but for now we have a brief overview:

  • Specify which HTML elements we’d like to animate
  • Set timing (easing) functions to change the rate we switch between properties
  • Specify the duration of how long the animation should take
  • Animate the elements using a small variety of CSS properties

Email animation techniques

As email developers we’re used to having limited support for web techniques in email and, unfortunately, CSS animations are no exception. Following are a couple ways you can add animation to emails with at least moderate support. If you know of any other clever techniques let me know in the comments and I’ll add them to the list!


One of the most common animation techniques around, a simple rotate can add a lot to your email technique. We’ll also break down each line of code to see what’s really going on.

Here’s what we’re going to achieve:

Meme cat gif

Here’s the code that handles the animation.

@-moz-keyframes spin { 100% { -moz-transform: rotate(360deg); } }
@-webkit-keyframes spin { 100% { -webkit-transform: rotate(360deg); } }
@keyframes spin { 100% { -webkit-transform: rotate(360deg); transform:rotate(360deg); } }

So, let’s look at what’s going on here! This bit of code:


Is the magic ticket, we use this to control the animation. It’s pretty simple, but you can see we’re simply telling the browser to “transform” the CSS element. The transform we’re calling in is the rotate transformation and we’re going to rotate it 360 degrees.

Then, the rest of the code is simply covering different browsers and email clients. You can see we’re targeting Mozilla clients, WebKit clients and non Webkit clients alike. If you’d like to read more about the different types of web browser and WebKit vs non-WebKit I’d recommend this fantastic Stackoverflow question.

So, now we’ve set up the CSS animation we simply need to declare it for the element(s) we wish to animate. Simply create a class and call the animation we created, named “spin” like so:

.spin {
-webkit-animation:spin 4s linear infinite;
-moz-animation:spin 4s linear infinite;
animation:spin 4s linear infinite;

You can see we’ve done what we did before with calling the animation for Mozilla, WebKit and non WebKit clients. All we’re doing here is telling the browser that any element with the class spin applied to it, we want to call our animation and have it spin for 4 seconds for an infinite loop.

Pretty simple right? How about checking out some more modifications


Here we’re going to use the same principles as we just looked at above to create a fading animation. This is what we’re going for:

fading gif

Again, just like above, we’re going to target the three main different browser types to ensure our code appears in every possible client it can.

@-webkit-keyframes fade {
0%   { opacity: 0; }
50% { opacity: 1; }
100% { opacity: 0;}

@-moz-keyframes fade {
0%   { opacity: 0; }
50% { opacity: 1; }
100% { opacity: 0;}

@keyframes fade {
0%   { opacity: 0; }
50%  { opacity: 1; }
100% { opacity: 0;}

The big difference here is that we’ve thrown in some extra keyframes. All this means is that at 0% of the animation cycle the opacity will be 0, at 50% or halfway through it’ll be 1 and then at 100% of the animation cycle it’ll be back at 0 opacity.

By using this keyframe method, we can control exactly what we want our animation to do and when. By having it start and end on 0 opacity, we create a nice fading loop.

We call it exactly the same was as we did for the rotation:

.fade {
-webkit-animation:fade 3s linear infinite;
-moz-animation:fade 3s linear infinite;
animation:fade 3s linear infinite;

Pretty easy to achieve!

Simulated “Loading Bar”

Here we’re going to use a sequence of changing background colours to mimic the effect of a loading bar, like so:

simulated loading bar

As this code is a bit longer and a bit more complicated, I’ve put it onto Codepen so we don’t fill the page but I’ll be referencing the code here.

For the full working code see here.

Basically, what we’re doing here is creating 5 different animations. Each one has 5 stages of animation:

  • 0%
  • 25%
  • 50%
  • 75%
  • 100%

We colour each box black to create this effect at a different stage of the animation. For example the first box has this:

0% { background: #000000}
25% { background: #ffffff }
50% { background: #ffffff }
75% { background: #ffffff }
100% { background: #ffffff }

All we’re saying here is that the first 25% of the animation cycle the background colour will be black for that box.

On the third box we have the same sort of thing, but the cycle will change the box to black at the third 25% of the animation:

0% { background: #ffffff}
25% { background: #ffffff }
50% { background: #000000 }
75% { background: #ffffff }
100% { background: #ffffff }

If you look at the full code, you’ll also notice we still make sure to target the three browser types – hence why the code is so long!

Background animations

A really powerful feature we have access to is the ability to animate backgrounds. This is one of my favourite ways to add subtle animations to give your emails an edge without having to worry about fallbacks because when it doesn’t animate it’s just a regular background.

Please note: I haven’t included VML fallbacks for Outlook background images in this code sample, so you’ll need to add them yourselves.

This is the effect we’ll be creating:

Background animations

Check out the working code sample before you get started.

So how do we create this amazing effect? Again, it’s all about getting your head around what’s supported and how to use keyframe animations.

This one is a bit less convoluted than above.

We’re telling the background image to scroll to a pixel value that’s either in a positive or negative direction from the starting point of the background.

@keyframes animatedBackground {
0% { background-position: 650px 0; }
100% { background-position: 0 0; }

@-moz-keyframes animatedBackground {
0% { background-position: 650px 0; }
100% { background-position: 0 0; }

@-webkit-keyframes animatedBackground {
0% { background-position: 650px 0; }
100% { background-position: 0 0; }

We can modify this further by adding images/text on top of the scrolling background to create clever animations like display block did in part one.

Code drawbacks of CSS email support

Please note; although I’ve researched this blog fully, people are always stumbling across new techniques and code in email so if you believe any of this to be wrong or outdated, please reach out and let me know.

Repeating animations

One of the major drawbacks is the lack of email support for animation-iteration-count. This is the property that enables us to control the amount of times an animation loops for. This means we can either have an animation repeat once or forever. This is a pretty heavy drawback, but there’s still lots of amazing animations you can do in emails (as seen in the examples above) with continuous looping.

Delaying animations

Another pretty annoying drawback is the lack of support for the animation-delay property. This is the CSS snippet that allows us to delay how long before an animation triggers and starts. This means that all of our animations will start as soon as the email loads. Again, annoying!

Scroll based/Scroll triggered animation

I have a lot of people ask me about this but unfortunately, we can’t do it. It’s a technique we see a lot of on the web but it actually uses a sub-branch of JavaScript, jQuery, to handle the scroll based triggers to then call in the CSS animations. It’s a beautiful technique, but we all know the pitfalls of trying to get JavaScript to work in an email!


CSS animations are a great way to enhance your emails that are often overlooked by lots of developers, designer and marketers. As a developer I see it as my job to make sure an email works everywhere. But, I also see it as my job to enhance emails for those with clients that support further enhancements (like animations). We should be aiming to give everyone the best possible experience in our emails, regardless of the email client.

As a closing note, this blog features lots of code samples that could become outdated at any point. If you find anything not working in this blog then please reach out let me know! Alternatively, if you have any suggestions for cool animation effects you’d like to see visualised let me know and I’ll give it a go.

Author: Alex Ilhan

Hailing all the way from England, Alex brings his email development expertise along with an endless stream of cups of tea and British cynicism. Follow him on Twitter: @omgitsonlyalex.

3 thoughts on “The Ultimate Email CSS Animation Guide: Part 2”

  1. Hei Alex.

    Thanks for the hint to use animations in emails.

    You’re mentioning the drawback of delaying animations.

    Actually, this drawback is non-existent, because one can work around by holding the animation from `from` to f.e. `10%` in the keyframes.

Comments are closed.

Free Email Goodies