Skip to content

Latest commit

 

History

History
310 lines (249 loc) · 21.7 KB

2015-05-22-buffer.md

File metadata and controls

310 lines (249 loc) · 21.7 KB
layout title description categories imageURL home_image tweet_text custom_header demo_url customCSS customJS source
post
Buffer's loading animation
Using CSS and SVG to create lightweight yet smooth animation
animation
loader
svg
how-to
/images/posts/buffer/buffer.png
/images/posts/buffer/buffer.png
CSS animation with SVG to create a simple loader effect
posts/buffer.html
buffer.css
buffer.js

I love finding examples of subtle animation in websites. Recently, when I was logging into Buffer, 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:

Buffer loading animation

The animation is achieved using an animated GIF file.

Buffer icon gif

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 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 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.

Tracing the image using 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:

<svg width="100%" height="100%" x="0px" y="0px" viewBox="0 0 313.3 321.4" style="enable-background:new 0 0 313.3 321.4;" xml:space="preserve">
  <path class="layer layer1" d="M157.1,0c3.8,0,7.9,1.5,11.4,3.2c45.6,21.1,91.2,42.4,136.7,63.8c3.3,1.5,8,2.1,8.1,7c0.1,5-4.7,5.6-7.9,7.1
c-45.8,21.5-91.7,42.9-137.6,64.3c-7.4,3.4-14.8,3.5-22.2,0C99,123.6,52.3,101.9,5.8,80c-2.4-1.1-5.4-4-5.4-6c0-2,3.1-4.8,5.5-5.9
C52.4,46.2,99.1,24.4,145.8,2.8C149.1,1.2,154.5,0,157.1,0z"/>
  <path class="layer layer2" d="M156.6,235c-3.1,0-7.7-1.7-11.3-3.3c-46.5-21.6-93-43.3-139.4-65.1c-2.4-1.1-5.8-4.1-5.6-5.8c0.3-2.4,3.2-5,5.7-6.3
c7.5-4,15.3-7.3,23-10.9c7.9-3.7,15.7-3.6,23.6,0.1c30.4,14.3,61,28.4,91.4,42.7c8.6,4.1,16.8,4,25.4-0.1
c30.4-14.3,60.9-28.4,91.4-42.7c7.7-3.6,15.4-3.7,23.1-0.1c8.2,3.8,16.4,7.4,24.4,11.5c2.1,1.1,4.9,3.7,4.7,5.4
c-0.2,2.1-2.7,4.8-4.9,5.9c-46.8,22.1-93.7,44-140.7,65.8C164.2,233.5,159.9,235,156.6,235z"/>
  <path class="layer layer3" d="M156.8,321.4c-4.6,0-9.3-2.3-13.4-4.2c-45.2-20.9-90.3-42-135.4-63.1c-3.3-1.5-8-2.1-8-7.1c0-5,3.8-5.5,7-7.1
c13.9-6.5,14.9-6.5,21.8-9.8c8-3.8,16-3.7,24.1,0.1c29.9,14,59.8,27.7,89.6,41.9c9.6,4.6,18.5,4.7,28.2,0.1 c29.8-14.2,59.8-27.9,89.6-41.9c8.2-3.9,16.3-4,24.5,0c7.8,3.8,15.8,7.2,23.5,11.1c2.1,1.1,4.8,3.3,4.8,5.4
c-0.1,2.4-2.7,4.8-4.9,5.9c-32.2,15.3-64.5,30.3-96.8,45.4c-13.9,6.5-27.7,13.1-41.7,19.3C165.7,319.2,161.5,321.4,156.8,321.4z"/>
</svg>

Here's the result:

Download this SVG here

Styling SVG layers

You may have noticed the class parts of the SVG. I added these so that I can style the SVG using CSS.

There are some attributes we can style with CSS, including stroke, fill and even adding CSS filters. For this example I'll be working on the fill property, which is like background-color.

One thing worth noting: When we reference SVG images using the img tag, we can't style the contents of the SVG with CSS. In this example I'm including the text of the SVG file directly in the source. This allows the CSS to work on it.

We can give the layers the Buffer grey colour using this CSS:

.layer {
  fill: #4b4b4b;
}

Animating

We can use keyframe animation to create the loading animation effect. When planning out animations like this, I like to turn to pen and paper and structure the animation. The goal is to have 3 animations, all looping in sync.

Timeline of the animations on the layers

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.

Scaling it down

Let's see how it sits alongside the real logo:

Pretty sweet!

The result is small (~3Kb in total including CSS, using Gzip), scales to retina and beyond, and can be easily changed in CSS if needed. The animation can also be stopped using a little JavaScript rather than swapping out another image. See this in action in the demo.

Taking it further

Since we've used CSS to set up the animation, we can try variations without changing the SVG file.

Download the files

You can download the finished HTML and CSS here.

Browser compatibility

Thankfully SVG has become mainstream. A site I often check for these things is CanIUse.com. Here we see decent support for SVG across all modern browsers. However if you want to make sure your visitors in older browsers have a good experience, I'd recommend using Modernizr and serving a static image.