Search code examples
cssanimationsvgrotationcss-transforms

Why is this CSS rotation transform of a spinner bobbing up and down?


I have a simple Spinner icon I created in Figma. It should be aligned on the x, y center of the enclosing frame, which is 64x64. I have added a rotation to it using CSS here:

let rotation = 0;

function incrementAnimationFrame() {
  rotation = (6 + rotation) % 360;
  $('#rotationBlock').css('transform', `rotate(${rotation}deg)`);

  requestAnimationFrame(incrementAnimationFrame);
}

requestAnimationFrame(incrementAnimationFrame);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="rotationBlock" style="display: block; width: 160px; padding: 0px; margin: 0px;">
  <svg preserveAspectRatio="xMidYMid meet" fill="#FFD041" height="160px" viewBox="0 0 64 64">
    <path d="M35.6561 2.22362C43.2296 3.15353 50.1642 6.9344 55.0485 12.7967C59.9328 18.659 62.3997 26.1622 61.9472 33.7792C61.4947 41.3962 58.1567 48.5545 52.6126 53.7972C47.0686 59.04 39.7351 61.9732 32.1047 61.9998C24.4744 62.0265 17.1206 59.1445 11.5401 53.9406C5.95953 48.7367 2.57166 41.6019 2.06596 33.9882C1.56025 26.3746 3.97473 18.8544 8.81798 12.9581C13.6612 7.06183 20.5692 3.23264 28.1361 2.24987L28.9859 8.79255C23.0831 9.55919 17.6943 12.5463 13.9162 17.1458C10.1381 21.7454 8.25459 27.6118 8.64908 33.551C9.04357 39.4902 11.6864 45.0559 16.0396 49.1154C20.3929 53.1749 26.1294 55.423 32.0817 55.4022C38.034 55.3814 43.7547 53.0933 48.0795 49.0036C52.4043 44.9138 55.0082 39.3298 55.3612 33.3879C55.7142 27.4461 53.7898 21.593 49.9797 17.0199C46.1695 12.4468 40.76 9.49747 34.852 8.77207L35.6561 2.22362Z"></path>
  </svg>
</div>

https://codepen.io/jwir3/pen/dyvEQKa

As you can see, the rotation bobs slightly up and down, which I think has something to do with the viewBox of the SVG and the alignment of the center of the Spinner.

I'm wondering if there is something I can do to alleviate this "bobbing". Is it possible that Figma doesn't quite have the center of the vector image aligned just right?


Solution

  • This happens because your SVG does not fit 100% into your div. The div is a bit higher than the SVG, you can see it when you inspect the element in your browser.

    As a solution I would say don't rotate the div but rather the SVG directly. If you need to rotate the div (because of multiple nested elements) make sure that the dimensions of the element are correct and not too big.

    btw, setting display: block for a div is not needed since this is it's default value.

    let rotation = 0;
    
    function incrementAnimationFrame() {
      rotation = (6 + rotation) % 360;
      $('#rotationBlock').css('transform', `rotate(${rotation}deg)`);
    
      requestAnimationFrame(incrementAnimationFrame);
    }
    
    requestAnimationFrame(incrementAnimationFrame);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <svg id="rotationBlock" preserveAspectRatio="xMidYMid meet" fill="#FFD041" height="160px" viewBox="0 0 64 64">
        <path d="M35.6561 2.22362C43.2296 3.15353 50.1642 6.9344 55.0485 12.7967C59.9328 18.659 62.3997 26.1622 61.9472 33.7792C61.4947 41.3962 58.1567 48.5545 52.6126 53.7972C47.0686 59.04 39.7351 61.9732 32.1047 61.9998C24.4744 62.0265 17.1206 59.1445 11.5401 53.9406C5.95953 48.7367 2.57166 41.6019 2.06596 33.9882C1.56025 26.3746 3.97473 18.8544 8.81798 12.9581C13.6612 7.06183 20.5692 3.23264 28.1361 2.24987L28.9859 8.79255C23.0831 9.55919 17.6943 12.5463 13.9162 17.1458C10.1381 21.7454 8.25459 27.6118 8.64908 33.551C9.04357 39.4902 11.6864 45.0559 16.0396 49.1154C20.3929 53.1749 26.1294 55.423 32.0817 55.4022C38.034 55.3814 43.7547 53.0933 48.0795 49.0036C52.4043 44.9138 55.0082 39.3298 55.3612 33.3879C55.7142 27.4461 53.7898 21.593 49.9797 17.0199C46.1695 12.4468 40.76 9.49747 34.852 8.77207L35.6561 2.22362Z"></path>
      </svg>