Select Page

As my code of the Android Nougat loading rings got quite a bit of interest on codepen.io last week, I thought I’d do a quick CSS animation tutorial to show how I pieced it together.  The code is actually quite simple- it just consists of 4 different coloured rings that rotate in a loop with a bit of deformation to give it that ‘wobbly’ look.

Here’s a demo of the finished animation:

So lets start with something simple first: creating one of the rings.  There’s no fancy CSS here to cut a transparent hole in the middle of a circle or anything, it’s just a circular div with a thick border.

HTML:

<div class="ring"></div>

CSS:

.ring {
  width: 300px;
  height: 300px;
  border: 20px solid #d50f1c;
  border-radius: 50%;
}

Result:

Now lets animate this ring! Animation in CSS can appear quite confusing at first (even to myself, who has a degree in animation!) but if you try and think about it as simply as you can, you should be able to keep on top of it.

The timeline of a CSS animation is done in percentages which is great as it means you can change the duration whenever you want, even after you’ve set all your keyframes. So the very beginning of the animation will be at ‘0%’ and the very end at ‘100%’.

For example if I wanted to animate a very simple ball bounce, I would have a keyframe at 0% with the ball high in the air, a keyframe at 50% with the ball touching the ground, and a final keyframe at 100% with the ball back up in the air where it started.

If you want to have a play around with CSS animation or just work better visually, then check out cssanimate.com. It’s a really useful online tool that you can use to interactively create the animation you want right in your browser window. Although I would still recommend to spend some time to understand the code, it’s still great for more complex animation.

So back to our ring. To create the wobble effect, we can use a scale animation to distort the ring.

CSS:

@keyframes red-ring-anim {
  0%   {transform: scaleY(1.0);}
  50%  {transform: scaleY(0.9);}
  100% {transform: scaleY(1.0);}
}

To apply this animation to our ring, we just need to add a bit of CSS on the .ring class, to specify duration, looping and where to find the animation.

CSS:

.ring {
  width: 300px;
  height: 300px;
  border: 20px solid #d50f1c;
  border-radius: 50%;
  animation-name: red-ring-anim; //specifies which set of keyframes you would like to apply.
  animation-duration: 4s; //how long in seconds you would like you animation to take.
  animation-iteration-count: infinite; //how many times you would like the animation to loop.
}

Result:

Finally we have some movement going on, though it looks a little boring and robotic at the moment. So lets add some more keyframes, and while we’re at it, we’ll add some animation to the scaleX as well.

CSS:

@keyframes red-ring-anim {
  0%   {transform: scaleX(1.0) scaleY(0.9);}
  25%  {transform: scaleX(0.9) scaleY(1.0);}
  50%  {transform: scaleX(1.0) scaleY(0.9);}
  75%  {transform: scaleX(0.9) scaleY(1.0);}
  100% {transform: scaleX(1.0) scaleY(0.9);}
}

Result:

And finally, the last bit of animation we can add to this ring is a rotation. To make it loop seamlessly, we want it to be at 0 degrees at 0% and 360 degrees at 100%. We can go ahead and and the animation to the keys we already have.

CSS:

@keyframes red-ring-anim {
  0%   {transform: scaleX(1.0) scaleY(0.9) rotate(0deg);}
  25%  {transform: scaleX(0.9) scaleY(1.0) rotate(90deg);}
  50%  {transform: scaleX(1.0) scaleY(0.9) rotate(180deg);}
  75%  {transform: scaleX(0.9) scaleY(1.0) rotate(270deg);}
  100% {transform: scaleX(1.0) scaleY(0.9) rotate(360deg);}
}

Now lets add three more rings, and apply a different colour class to each one.

HTML:

<div class="container">
  <div class="ring red"></div>
  <div class="ring green"></div>
  <div class="ring blue"></div>
  <div class="ring yellow"></div>
</div>

As for the animation on the other rings, they need to all be subtly different from each other to get that offset look to it. When I orginally wrote this code, it was a lot of trial and error, changing some values and seeing what happens. It’s a great way to learn, especially on sites like codepen.io, jsfiddle.net, dabblet.com, etc where you get instant feedback. Feel free to have a look through the values I used below.

CSS:

.container {
  width: 300px;
  height: 300px;
  position: relative;
}
.ring {
  width: 300px;
  height: 300px;
  border-radius: 50%;
  position: absolute;
}
.red {
  border: 20px solid #d50f1c;
  animation: redanim linear 6s;
  animation-iteration-count: infinite;
}
.green {
  border: 20px solid #009927;
  animation: greenanim linear 6s;
  animation-iteration-count: infinite;
}
.blue {
  border: 20px solid #3569e1;
  animation: blueanim linear 6s;
  animation-iteration-count: infinite;
}
.yellow {
  border: 20px solid #edb40f;
  animation: yellowanim linear 6s;
  animation-iteration-count: infinite;
}

@keyframes red-ring-anim {
  0%   {transform:  rotate(0deg)   scaleX(0.90) scaleY(1.00);}
  50%  {transform:  rotate(180deg) scaleX(0.90) scaleY(1.00);}
  100% {transform:  rotate(360deg) scaleX(0.90) scaleY(1.00);}
}

@keyframes green-ring-anim {
  0%   {transform:  rotate(31deg)  scaleX(0.90) scaleY(1.00);}
  25%  {transform:  rotate(121deg) scaleX(1.00) scaleY(0.90);}
  50%  {transform:  rotate(211deg) scaleX(0.90) scaleY(1.00);}
  75%  {transform:  rotate(301deg) scaleX(1.00) scaleY(0.90);}
  100% {transform:  rotate(391deg) scaleX(0.90) scaleY(1.00);}
}

@keyframes blue-ring-anim {
  0%   {transform:  rotate(413deg) scaleX(0.90) scaleY(1.00);}
  50%  {transform:  rotate(233deg) scaleX(0.90) scaleY(1.00);}
  100% {transform:  rotate(53deg)  scaleX(0.90) scaleY(1.00);}
}

@keyframes yellow-ring-anim {
  0%   {transform:  rotate(472deg) scaleX(0.90) scaleY(1.00);}
  25%  {transform:  rotate(382deg) scaleX(1.00) scaleY(0.90);}
  50%  {transform:  rotate(292deg) scaleX(0.90) scaleY(1.00);}
  75%  {transform:  rotate(202deg) scaleX(1.00) scaleY(0.90);}
  100% {transform:  rotate(112deg) scaleX(0.90) scaleY(1.00);}
}

Result:

 
 
The final addition to this project is one that I think really sells this animation and a bit of code that is not very often used.

mix-blend-mode: screen;

mix-blend-mode behaves in the same way you would expect using blending modes in programs like Photoshop. There’s a really good selection of blending modes you can choose from, but here’s just a few examples so you can see what the effect is.

Screen
Multiply
Color

For this project, we’ll use ‘screen’ and apply it to .ring and give the body tag a black background.

CSS:

body {
  background: black;
}

.ring {
  width: 300px;
  height: 300px;
  border-radius: 50%;
  position: absolute;
  mix-blend-mode: screen;
}

Final result:

I hope you enjoyed this tutorial and learnt something new from it! If you have any questions, please feel free to post a comment below or send me an email directly.