Search code examples
htmlcsscss-shapes

How do I draw a spinner with pure CSS?


I first tried implementing it through two triangles. And got a satisfactory output

#wrapper {
  margin-left: 40vw;
  margin-top: 20vh;
}

#fidgetu {
  width: 0;
  height: 0;
  position: absolute;
  margin-top: 3vh;
  border-left: 50px solid transparent;
  border-right: 50px solid transparent;
  border-bottom: 100px solid red;
  animation: rotate 2s linear infinite;
}

#fidgetd {
  width: 0;
  height: 0;
  position: absolute;
  margin-top: 3vh;
  border-left: 50px solid transparent;
  border-right: 50px solid transparent;
  border-top: 100px solid red;
  animation: rotate 2s linear infinite;
}

@keyframes rotate {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}
<div id="wrapper">
  <div id="fidgetu">
  </div>
  <div id="fidgetd">
  </div>
</div>

I guess drawing a fidget spinner would require 4 div circles and 3 div rectangles to connect the central circle to the other three and a wrapper div (applying animate property to this div). But the positioning is messing up.

Now how do I position them appropriately such that the entire block rotates around its center?


Solution

  • Set an element as the base spinner, and then 3 childs of this one as the outer circles.

    if the outer ones are positioned over the first one, just rotating the base elements will handle the rotation of the others.

    A litlle tricky are the curves connecting the inner and the outer. I have set a solution, but there is some misalignment. It still needs a last adjustment on the pixel values (but it's hard to get it exactly)

    .spinner, .outer {
      width: 100px;
      height: 100px;
      border-radius: 50%;
      position: absolute;
      transform-style: preserve-3d;
    }
    
    .spinner {
      background-color: teal;
      border: solid 20px tomato;
      margin: 100px;
      animation: rotate 4s infinite linear;
    }
    
    .outer {
      background-color: lightblue;
      border: solid 20px blue;
      left: -20px;
      top: -20px;
    }
    
    .outer:before {
       content: "";
       position: absolute;
       width: 150px;
       height: 150px;
       border-radius: 50%;
       transform: translate(-91px, 104px);
       box-shadow: 0px -55px 0px -33px blue;
    }
    
    .outer:after {
       content: "";
       position: absolute;
       width: 150px;
       height: 150px;
       border-radius: 50%;
       transform: translate(-83px, -156px);
       box-shadow: 0px 55px 0px -33px blue;
    }
    
    
    .outer:nth-child(1) {
       transform: translate3D(120px, 0px, -10px);
    }
    
    .outer:nth-child(2) {
       transform: rotate(120deg) translate3D(120px, 0px, -10px);
    }
    
    .outer:nth-child(3) {
       transform: rotate(240deg) translate3D(120px, 0px, -10px);
    }
    
    @keyframes rotate {
      from {transform: rotate(0deg);}
        to {transform: rotate(360deg);}
    }
    <div class="spinner">
        <div class="outer"></div>
        <div class="outer"></div>
        <div class="outer"></div>
    </div>