How Did They Do That? The Twitter “Like” Animation.

Or, An Introduction to CSS Sprite Sheet Animation.

By now, you’ve probably seen or heard — the Twitter star has been replaced with a little heart, and the “favorite” has been re-dubbed the “like.”

Regardless of whether you love or hate the change, the new like animation is a great example of how CSS sprite sheets can be used to bring really awesome animation to the web.

The Animation

Image for post
Image for post
The new animation, copyright Twitter, probably.

I won’t go into detail on the actual process of designing the animation in this post, because I don’t know the process they used— you can go ask Brian Waddington if you’d like to know.

Getting it into the browser is a different story.

In order to get this animation to display fast and fluidly on the web, the Twitter team utilized a technique made famous in video games of old known as sprite sheet animation.

This process involves exporting each frame of the animation side-by-side into a single image, so that instead of loading 29 different assets to play a simple animation, you just have to load one.

Why is this so important? Trips to and from the server are expensive from a speed and resource standpoint, and when you have 320 million active users on your site, small savings result in huge performance gains. Making one trip instead of 29 is one great way to optimize.

Image for post
Image for post
The actual image used for the animation on the web version of Twitter.

Once the animation has been compiled into one image as seen above, we can “flip” through the frames using CSS, emulating animation techniques made famous by Flipbooks and the Zoetrope.

So, how do we animate it?

The Code

In order to replicate what the folks at Twitter did, we’ll need three things:

First, we’ll make a pretty straight-forward div:


<div class=”heart”></div>


.heart {
cursor: pointer;
height: 50px;
width: 50px;
background-image:url( ‘');
background-position: left;

If you know CSS, you should understand what’s going on here. We give the div a set width and height, make it’s background image the sprite-sheet, position that background image all the way to the left (which will be the first frame of the animation), and then set it’s background size to be 2900% so that it will properly fill the div. We also set the cursor to a pointer so the user knows it’s clickable.

Here’s what we have so far:

Image for post
Image for post

Next, the fun part — animating it! Alright, so it’s not that fun, but it is very straightforward.


@keyframes heart-burst {
from {background-position:left;}
to { background-position:right;}

What we’ve done here is define a custom CSS keyframe animation. We’re telling CSS to animate the background position from the left to the right, and we’re naming it heart-burst.

Note: We’ve left it out, but you’ll need to use proper vendor prefixes for cross-browser support. More info here.

Now that we’ve defined the animation, we can play it by adding this to our heart div:

.heart {
animation: heart-burst 1s infinity;

This simply says play the animation named heart-burst, which we defined above, for a duration of 1 second, and loop it indefinitely.

If we apply the animation this way, we’ll get something like this:

Image for post
Image for post
Ludicrous speed!

Obviously not what we were going for, but close!

To make it display properly, we’ll need to utilize steps(). This will allow us to break up the animation into individual segments, so instead of smoothly animating from left to right, we’ll do it in a number of chunks that syncs up with our number of frames.

While we’re at it, we’re also going to break out the animation into a separate class, so that the animation will only play when that class is applied to the div. This way, we can trigger it whenever we want.

.is_animating {
animation: heart-burst .8s steps(28) 1;

Here, we’re saying play the animation named heart-burst for a duration of 0.8s, and do it in 28 frames. When we apply this class to our heart div, we should get this:

Image for post
Image for post

Now that we have a working animation, the last thing to do is trigger it when a user clicks.

I’ll use good ‘ol jQuery for that:

$(“.heart”).on(‘click’, function(){
$(“.heart”).on(‘animationend’, function(){

Here, the first event listener waits for the user to click, and then toggles our ‘is_animating’ class to be applied to the heart, triggering the animation.

The second listener waits for the animationend event, which is fired when a CSS animation completes, and then removes the ‘is_animating’ class, so when we click it again, we’ll see the animation again.

And last but not least, let’s add a hover effect to complete the experience:

.heart:hover {

The Final Product

Image for post
Image for post
We did it!

And there you have it!

Check out the full code here, or go inspect the actual element on Twitter.

Want to learn more about CSS animation? Here are a few good resources:

Written by

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store