Select Page

I came across a gif online of this really mesmerising illusion so I thought I’d have a go at coding it myself with CSS and I discovered some interesting results along the way…

My first port of call was to get the concentric circles set up with the ability to make one quarter of the ring black and the opposite quarter white.  The easiest way to do this is with borders.

To see how it works, here’s a plain, square div with a large 30px border and each side set to different colours:

HTML:

<div class="circle"></div>

CSS:

.circle {
width: 100px;
height: 100px;
border-top: 30px solid #EB5652;
border-bottom: 30px solid #EB9952;
border-left: 30px solid #328A8E;
border-right: 30px solid #41B949;
}

 

 

And if we add a border-radius (equal to the width and height of the div) to that, we can turn it into a circle:

CSS:

.circle {
width: 100px;
height: 100px;
border-top: 30px solid #EB5652;
border-bottom: 30px solid #EB9952;
border-left: 30px solid #328A8E;
border-right: 30px solid #41B949;
border-radius: 100px; /* border radius is same amount as width/height */
}

 

 

So now all we have to do is make the top black, the bottom white, and either side match the background colour (we’ll make it grey).

HTML:

<div class="container">
  <div class="circle"></div>
</div>

CSS:

.container {
  background:grey;
}

.circle {
  width: 100px;
  height: 100px;
  border-radius:100px;
  border-top: 30px solid black;
  border-bottom: 30px solid white;
  border-left: 30px solid grey;
  border-right: 30px solid grey;
}

 

 

So the basic element of this project is done, now we just need to nest a few more of those circle divs and adjust a few width/height values.

HTML:

<div class="container">
  <div class="circle">
    <div class="circle">
      <div class="circle">
        <div class="circle">
          <div class="circle">
            <div class="circle">
              <div class="circle">
                <div class="circle">
                  <div class="circle">
                    <div class="inner"></div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

CSS:

.container {
  background:grey;
}

.circle {
  margin:5px;
  border-radius:660px;
  border-top: 30px solid black;
  border-bottom: 30px solid white;
  border-left: 30px solid grey;
  border-right: 30px solid grey;
}

.inner {
  width:30px;
  height:30px;
}

 

 
So with the HTML all we’ve done is nested as many divs with the ‘circle’ class as we want rings to appear, and added a final ‘inner’ div in the centre to give a bit of space. For the CSS, a margin has been added to space out the circles a little and the .inner class has a width and height given to it.

The the width and height of the .circle class has also disappeared. This is so they are able to scale themselves to fit inside each other. However, as you can see now the circles are no longer circles. To fix this, we need to make the container div the same width as the height and so therefore we need to figure out what value the height actually is.

There are a number of ways to figure out the height, from taking a screenshot of it and working it out in Photoshop to using Google Chrome’s developer tools to simply adjusting the width value until it looks about right. There is also a way to work it out just by the values we’ve already put in.

width of .container class = ([number of circle divs] x [border size] x 2) + [height of ‘inner’ div] + ([margin size] x [number of circle divs] x 2)

So once that’s worked out, here is what you’ll end up with:
 

 

Now onto animating them!

All that needed for this is to set the keyframes and to tell it what to do inbetween those keyframes.

CSS:

@keyframes mySpinAnimation {
  0%   { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

So all we’re saying here is simply at the very beginning, the element will be rotated by 0 degrees and at the very end, it will be rotated by 360 degrees. And to specify which element we want to rotate, we add this to the .circle class:

CSS:

.circle {
  animation: mySpinAnimation 20s infinite;  /*specify the name of the @keyframes you want to use, how long you want it to last (seconds) and 'infinte' to make it loop*/
  animation-timing-function: linear;  /*helps it loop seamlessly*/

  border-top:30px solid black;
  border-right:30px solid grey;
  border-left:30px solid grey;
  border-bottom:30px solid white;
  border-radius:620px;
}

 

Feel free to mess around with the CodePen below, try adding and removing lines and changing the colours and animation, you can get some pretty cool results with this!

See the Pen Spinning Illusion (Pure CSS) by chilli con code (@chilliconcode) on CodePen.