4 balls 10 spinners: CSS3 Animations

Loading spinners are lots of fun. Their main purpose is to let users know that the app is loading, but it has a secondary one that make them very special: they should amuse the users while they are waiting. If they are good, they even make the waiting time shorter. The spinner is probably the part of an application where the designer can be more creative, having the freedom for creating a funny animation in an environment traditionally marked by the static nature of most of the components.

My challenge is to create 10 different loading spinners using 4 circles and CSS3 animations to cheer them up. It is a good creativity exercise, that will make me explore some key parts of CSS3 animations and, what is better, show them to you. I hope they are inspiring, let's start!

1. Newton's cradle

See the Pen Newton's cradle by Javier Marquez (@arqex) on CodePen.

Hey! That doesn't spin, it is not a spinner! Well, it is common among loading animations to be circular, but I will start with some plain ones because they are simpler.

I will use the --prefix-free option offered by codepen in all the spinners, so the result CSS will be much easier to read.

In the Newton's cradle only two balls are animated. I get a natural movement updating the animation-timing-function inside a keyframe. animation-timing-function applies easing to every transition between keyframes. When the function is updated inside some keyframe, the transition to the following one will use that given function. Using ease-out when the ball is going away and ease-in when it is returning we have the desired pendulum effect.

2. Wave

See the Pen Wave by Javier Marquez (@arqex) on CodePen.

The timing function update inside a keyframe is also used in this spinner to ease the ball jump. Timings functions are really powerful, and for the wiping ball I am using a customized cubic-bezier value.

I expected the ease value to work here, but it was producing collisions with the jumping balls. That's because the ease value doesn't apply the same easing for the beginning than for the end of the animation, so I had to use cubic-bezier to get the effect I want. I would explain cubic-bezier curves here, but the easiest way to understand how they work is visiting cubic-bezier.com, its interactive graph is worth a thousand words.

3. Circus

See the Pen Circus by Javier Marquez (@arqex) on CodePen.

Here we are spinning. Well, sort of... I will only use 2D transformations to create my spinners, so here there are just moving and scaling.

I use two animations for every ball. When you apply more than one animation to the same element, all of them run at the same time and , unfortunatelly, there is no way to create a queue using CSS3. But in this case is good enough.

Circus uses negative animation-delay values to set the starting position and size of each ball, and make them spin from the begining. As you can see, CSS3 transforms are used to change the size and position of the balls. Transform are really handy for CSS3 animations, I like especially the scale one, that makes the balls grow or shrink respecting the center of the elements. That means the balls grow/shrink to the same proportion to the left/right horizontally and to the top/bottom vertically. If I had used width and height properties, the balls just would have grown/shrunk to the left and the bottom. By default, the origin of CSS3 transformation is the center of the element.

4. Atom

See the Pen Atom by Javier Marquez (@arqex) on CodePen.

Let's start creating animations less horizontal. I will use Circu's 3D effect to create some electrons spinning around a nucleus :)

Here the .ball elements are actually squares, and the circles that are shown are :before pseudo-elements positioned absolutely at the top left of the square. Every square is rotated to make the balls move with a different inclination. Try to uncomment the background property in the electron mixin to see what I mean.

Animating the z-index property in the ball containers, I could make the electrons go back and forth around the nucleus. Pay attention than in firefox, to animate z-index property, the element should have a z-index value set up, otherwise it won't work. Also the nucleus has a subtle scale animation that make the spinner feel more dynamic.

People from github, don't you like it for you atom editor? :)

5. Fussion

See the Pen Fussion by Javier Marquez (@arqex) on CodePen.

So far whe have animated the position and the size of the balls, but focusing in other properties we can get really different spinners. Fussion focus in background colors, and it is inspired by my of Nexus 7's boot animation.

It is a basic strategy for every spinner to render the balls in the same state that they had in the begining of the loop, in order to make possible repeat the animation infinitely. In this case, every ball is transformed in the next one to get ready for the next loop. Making the balls semi-transparent creates the effect of color fussion when they are all together.

6. Mitosis

See the Pen Mitosis by Javier Marquez (@arqex) on CodePen.

Mitosis uses an alternate value for the animation-direction property, that means that when the animation finishes, goes backwards to the begining again. That way the balls can split at the begining and merge at the end coding just the half of the animation.

But, if you look at the animation the balls are not merged in the same direction than they were splitted, that's because the whole spinner is rotated 90 degrees in the middle of the loop, using the step(2, end) value for the animation-timing-function. The step function make the animations complete rendering just the number of frames given to the function. In our case 2 frames, the first is rotated 0 degrees and the second 90. The end of the animation (a 180º rotation) is never visible because a new loop starts again.

Another trick used in Mitosis is the deformation of the balls, they are scaled horizontally and vertically asynchronously, showing a really interesting jelly effect.

7. Flower

See the Pen Flower by Javier Marquez (@arqex) on CodePen.

First spinner here! Remember when I explained at Circus spinner that I said that by default the CSS3 transformations have the center of the object as origin by default? In flower, all the transformation's origins for the balls have been moved to the center of the spinner. That way the balls use that point as the center of the rotation instead their own center, so they can rotate as if they were one circle. transform-origin is the property that let us customize the center of all the transformations.

Thanks to LESS the calculation of the origin is a bit easier. In this spinner I wish I had some way of enqueueing the animations, because calculate the keyframes position manually was really painful.

8. Clock

See the Pen Clock by Javier Marquez (@arqex) on CodePen.

Sometimes, to make some element spin, it is not necessary to change the transform-origin. In this case, :before pseudo-elements are used to render the balls, the same way they were in Atom spinner. So every .ball element is really a square, and the ball is placed in its top left. Rotating those squares we can make all the balls spin using the same center.

The step function is again used in the .spinner element to create the effect of whole spinner rotation in every loop of the ball group.

9. Washing machine

See the Pen Washing machine by Javier Marquez (@arqex) on CodePen.

Here the borders are the starring of the spinner, but, in this case, none of the balls is animated. The whole spinner is what is rotated, very fast, and alternating the direction thanks to the animation-direction property.

In this spinner :before pseudoelements are used for rendering the small balls, and the .ball elements are rotated to place the balls in different points of the big border. Again, LESS is really helpful to make all the calculations needed to center the balls in their container.

10. Pulse

See the Pen Pulse by Javier Marquez (@arqex) on CodePen.

This is an example of how diverse spinners can be made if we focus in different css properties. The main property animated here is border, with a little help of the opacity one to create a bubbling effect.

This is not a complex slider because every ball uses the same animation. Here again, animation-delay is our friend to make every ball bubble at their time.

Conclusion

Here it is where I am supposed to say "Animations are awesome, come on! Use them!". They have very strong points:
  • No need of any external libraries.
  • The animations are hardware accelerated, so their performance is really good.
But creating the spinners I felt that they were made to create small effects. When you start to think bigger, the complexity of the code and calculations grows exponentially, making the use of css preprocessors almost mandatory for their development.

Also, browser support is not really big. At the moment of writing this article, only 23.8% of users will be able to see the animations if you don't use vendor prefixes, according to Can I Use, so you will need a css prefixer if you don't want to get old writing them all.

A way of making a queue of animations would be great to have. Currently, CSS transitions can be used to create a queue, but you need a touch of javascript too coordinate when to apply them.

The last issue I would like to point out is that it is impossible to apply transformations independently. For example, if you want to move an element from 0px to 130px and, and in the middle you want to scale it to a 200% you need to calculate manually also the position of the element in that middle point:

@keyframes my-animation {

0%{
  transform: translateX(0);
}
50%{
  transform: translateX(65px) scale(2,2);
}
100%{
  transform: translateX(130px);
}
}

It may seem not a big problem, but if you want to apply some easing function, it will be applied to the 50% keyframe too, so it will got slower/faster in the middle of the animation.

I wouldn't use any library just to create a spinner in my projects, but if I had to create an app with some complex animation I would really think about using some tool like velocity.js to make my life easier and gain some cross browser compatibility.

Your challenge

Did I tell you that spinners are fun? There is currently a challenge to create the best spinner using CSS3 animations at reddit. Web design community is always amazing, why don't to submit yours?
© arqex 2023
Someday,
we'll find ourselves
far, far away...
Transitions here have been created using a library of mine:
React interactable.
This awesome hyperspace effect thanks to this codepen from Noah Blon.
Software development can be fun!
Javier Márquez
Software developer