---
layout: post
title: Buffer's loading animation
description: Using CSS and SVG to create lightweight yet smooth animation
categories: [animation, loader, svg, how-to]
imageURL: /images/posts/buffer/buffer.png
home_image: /images/posts/buffer/buffer.png
tweet_text: CSS animation with SVG to create a simple loader effect
custom_header: posts/buffer.html
demo_url: https://cssanimation.rocks/demo/buffer/
customCSS: buffer.css
customJS: buffer.js
source: https://raw.githubusercontent.com/cssanimation/posts/master/2015-05-22-buffer.md
---
I love finding examples of subtle animation in websites. Recently, when I was logging into [Buffer](https://bufferapp.com), I noticed a nice loading effect in their logo. Here's how to recreate it using SVG and CSS.
## Indicating activity
When something takes longer than expected, it's a nice idea to include some visual feedback to tell your visitor that something is happening. One way is to have a subtle animation, or loading animation, on the page. Buffer's approach is to animate their logo:
The animation is achieved using an animated GIF file.
When the loading is complete, the animated GIF is swapped out for a static PNG version of the logo.
It can be tricky to cleanly swap an animated GIF with a static image, and in this case we see a slight "jump" as the two are switched.
Let's see if we can get around this by creating the animation and finished state using CSS.
## Why use CSS?
There are some significant advantages of using CSS instead of animated GIF files. The main advantage is size. While the animated GIF in use here is pretty small, at a mere 6Kb, the CSS needed to create a similar effect is a fraction of that. (The entire HTML and CSS on the demo page is 2.8Kb, including the heading and button styles).
CSS gives us the option to do more, while an animated GIF cannot be edited once created. Having said that, animated GIFs can be any animation at all, so may be suitable for more complex animation that couldn't be handled in CSS. For an example, see how the [Twitter fav animation](http://cssanimation.rocks/twitter-fave/) uses an image sprite to get around this.
Another advantage to using CSS is that it's resolution independent. We can scale it up to any size and it'll still look clear. To make the most of this, we can use an SVG image.
## Creating an SVG logo
Before creating an SVG I spent a while trying to create the Buffer logo using CSS. A similar effect can be seen on the [Fabric](https://get.fabric.io/) landing page, with 3 squares animating into place using CSS. Unfortunately the more subtle details in the Buffer layers meant it was too tricky, so I turned to SVG instead.
SVG (Scaleable Vector Graphics) is a type of vector image file. The files are made up of a series of paths, are infinitely scaleable and can be very efficient. There are various tools used to create them, including Sketch, Affinity Designer, and Adobe Illustrator.
In this case, I traced the PNG logo in Illustrator and tidied it up to create an SVG. The result is nice and efficient. Here it is in full:
Here's the result:
Keyframes describe animations as a series of steps from 0% to 100%. To illustrate this, I've marked out the areas where the layers need to be "on" to create a similar effect to the animated GIF.
We'll create three sets of keyframes, one for each of the layers:
@keyframes layer1 {
0%, 65% {
fill: #b2b2b2;
}
75%, 82% {
fill: #4b4b4b;
}
92%, 100% {
fill: #b2b2b2;
}
}
@keyframes layer2 {
0%, 40% {
fill: #b2b2b2;
}
50%, 86% {
fill: #4b4b4b;
}
96%, 100% {
fill: #b2b2b2;
}
}
@keyframes layer3 {
0%, 15% {
fill: #b2b2b2;
}
25%, 90% {
fill: #4b4b4b;
}
100% {
fill: #b2b2b2;
}
}
Each layer begins with the lighter grey (#b2b2b2) and then animates to the darker grey (#4b4b4b). I've also staggered the end of each animation so that it looks like the darker colour descends from the top to the bottom before repeating.
With the keyframes in place, we need to apply them to the layers.
.layer {
animation: 4s linear infinite;
}
.layer1 {
animation-name: layer1;
}
.layer2 {
animation-name: layer2;
}
.layer3 {
animation-name: layer3;
}
This applies each of those three sets of keyframes to the correct layer.