Using CSS to animate an SVG icon and make it spin in a clockwise direction from the center

I am attempting to rotate the inner path of this SVG so that it spins in a clockwise direction.

Currently, the path is spinning as if it were around a larger circle. How can I spin the icon from the center point and rotate it clockwise?

  #circle-arrows {
    animation: loader 1.25s infinite;
  }

  @keyframes loader {
    0% {
      rotate: 0deg;
    }

    100% {
      border-radius: 50%;
      rotate: 180deg;
    }
  }
<svg width="24" height="24" xmlns="http://www.w3.org/2000/svg">
    <g fill="none" fill-rule="evenodd">
      <path d="M0 0h24v24H0z" />
      <path
        d="M23 14.864C23 17.696 20.737 20 17.956 20c-.11 0-.236 0-.346-.016V20H6.044c-.11 0-.22 0-.33-.016C3.09 19.808 1 17.584 1 14.864c0-2.16 1.304-4.016 3.159-4.784.157-2.512 2.2-4.48 4.698-4.48.487 0 .959.08 1.399.224h.015A4.993 4.993 0 0 1 14.137 4c2.782 0 5.044 2.304 5.044 5.136 0 .24-.015.48-.062.72C21.35 10.4 23 12.432 23 14.864z"
        fill="#000" fill-rule="nonzero" />
      <path id="circle-arrows"
        d="M16.348 12.98c-.499 2.072-2.209 3.52-4.372 3.52a4.492 4.492 0 0 1-3.082-1.243l-.755.757a.376.376 0 0 1-.264.111.378.378 0 0 1-.375-.375v-2.625c0-.205.17-.375.375-.375H10.5c.205 0 .375.17.375.375 0 .1-.04.193-.11.264l-.804.802a2.991 2.991 0 0 0 4.594-.62c.14-.23.21-.452.31-.687.03-.082.087-.134.176-.134h1.125c.106 0 .187.088.187.187 0 .013 0 .03-.005.042zm.152-2.105c0 .205-.17.375-.375.375H13.5a.378.378 0 0 1-.375-.375c0-.1.04-.193.11-.264l.81-.809A3.016 3.016 0 0 0 12 9c-1.043 0-2.01.539-2.555 1.43-.14.229-.21.451-.31.686-.03.082-.087.134-.176.134H7.793a.189.189 0 0 1-.187-.187v-.042C8.11 8.94 9.838 7.5 12 7.5c1.149 0 2.267.457 3.099 1.243l.762-.757a.376.376 0 0 1 .264-.111c.205 0 .375.17.375.375v2.625z"
        fill="#FFF" fill-rule="nonzero" />
    </g>
  </svg>

Answer №1

One suggestion from @enxaneta is to include the CSS property transform-origin: center for the element with ID #circle-arrows. For more information on this, you can visit the following link: transform-origin.

#circle-arrows {
    animation: loader 1.25s infinite;
}

@keyframes loader {
    0% {
        rotate: 0deg;
    }

    100% {
        border-radius: 50%;
        rotate: 180deg;
    }
}
<svg width="24" height="24" xmlns="http://www.w3.org/2000/svg">
    <g fill="none" fill-rule="evenodd">
        <path d="M0 0h24v24H0z" />
        <path
            d="M23 14.864C23 17.696 20.737 20 17.956 20c-.11 0-.236 0-.346-.016V20H6.044c-.11 0-.22 0-.33-.016C3.09 19.808 1 17.584 1 14.864c0-2.16 1.304-4.016 3.159-4.784.157-2.512 2.2-4.48 4.698-4.48.487 0 .959.08 1.399.224h.015A4.993 4.993 0 0 1 14.137 4c2.782 0 5.044 2.304 5.044 5.136 0 .24-.015.48-.062.72C21.35 10.4 23 12.432 23 14.864z"
            fill="#000" fill-rule="nonzero" />
        <path id="circle-arrows"
            d="M16.348 12.98c-.499 2.072-2.209 3.52-4.372 3.52a4.492 4.492 0 0 1-3.082-1.243l-.755.757a.376.376 0 0 1-.264.111.378.378 0 0 1-.375-.375v-2.625c0-.205.17-.375.375-.375H10.5c.205 0 .375.17.375.375 0 .1-.04.193-.11.264l-.804.802a2.991 2.991 0 0 0 4.594-.62c.14-.23.21-.452.31-.687.03-.082.087-.134.176-.134h1.125c.106 0 .187.088.187.187 0 .013 0 .03-.005.042zm.152-2.105c0 .205-.17.375-.375.375H13.5a.378.378 0 0 1-.375-.375c0-.1.04-.193.11-.264l.81-.809A3.016 3.016 0 0 0 12 9c-1.043 0-2.01.539-2.555 1.43-.14.229-.21.451-.31.686-.03.082-.087.134-.176.134H7.793a.189.189 0 0 1-.187-.187v-.042C8.11 8.94 9.838 7.5 12 7.5c1.149 0 2.267.457 3.099 1.243l.762-.757a.376.376 0 0 1 .264-.111c.205 0 .375.17.375.375v2.625z"
            fill="#FFF" fill-rule="nonzero" transform-origin="center"/>
    </g>
</svg>

Answer №2

Opting to exclude CSS in favor of SVG SMIL animation

Tidied up the SVG using for conciseness

<svg viewBox="0 0 240 240" style="width:160px;background:pink">
  <path fill="#000" d="m230 149c0 28-23 51-50 51-1 0-2 0-3 0v0h-117c-1 0-2 0-3 0-26-2-47-24-47-51 
                       0-22 13-40 32-48 2-25 22-45 47-45 5 0 10 1 14 2h0a50 50 90 0138-18c28 
                       0 50 23 50 51 0 2 0 5-1 7 24 6 40 26 40 51z"/>
  <path fill="#fff" d="m163 130c-5 21-22 35-44 35a45 45 90 01-31-12l-8 8a4 4 90 01-3 1 4 4 90 
                       01-4-4v-26c0-2 2-4 4-4h28c2 0 4 2 4 4 0 1 0 2-1 3l-8 8a30 30 90 0046-6c1-2 
                       2-5 3-7 0-1 1 1-2-1h11c1 0 2 1 2 2 0 0 0 0 0 0zm2-21c0 2-2 4-4 4h-26a4 
                       4 90 01-4-4c0-1 0-2 1-3l8-8a30 30 90 00-20-8c-10 0-20 5-26 14-1 2-2 5-3 7 
                       0 1-1 1-2 1h-11a2 2 90 01-2-2v0c5-21 22-35 44-35 11 0 23 5 31 12l8-8a4 4 90 013-1c2 0 4 2 4 4v26z">
     <animateTransform attributeName="transform" type="rotate"
                       from="0 120 120" to="360 120 120" dur="4s" 
                       repeatCount="indefinite"/>
  </path>
</svg>

Answer №3

HTML-5 is amazing! You don't need to include the xmlns attribute.

Make sure to use a viewbox: the width and height are standard interface rendering elements just like any other HTML elements...

In SVG (or HTML), the reference point by default is located at coordinates { top:0, left:0 }, so any rotation is performed around this point.
The simplest way to position this point at the center of your SVG is by using transform-origin : center;, which also aligns with the center of your path featuring two curved arrows.

svg {
  width      : 180px;
  height     : 180px;
  background : lightblue;
  }
svg > .cloud {
  fill      : whitesmoke;
  }
svg > .circle-arrows {
  fill             : orange;
  transform-origin : center;
  animation        : loader 1.25s infinite;
  }
@keyframes loader {
    0% { rotate:   0deg; }
  100% { rotate: 180deg; }
  }
<svg viewbox="0 0 24 24">
  <path class="cloud" 
    d="M23 14.864C23 17.696 20.737 20 17.956 20c-.11 0-.236 0-.346-.016V20H6.044c-.11 0-.22 0-.33-.016
    C3.09 19.808 1 17.584 1 14.864c0-2.16 1.304-4.016 3.159-4.784...
    />
  <path class="circle-arrows"
    d="M16.348 12.98c-.499 2.072-2.209 3.52-4.372 3.52a4.492 4.492 0 0 1-3.082-1.243l-.755.757
    a.376.376 0 0 1-.264.111....
</svg>

Answer №4

To ensure proper rotation, you must specify the transform-origin as "center" or using explicit coordinates such as "12px 12px" - otherwise, the default origin values of 0,0 will be used.

If the rotation origin does not align with the viewBox, you can also combine transform-origin with transform-box:fill-box

 #circle-arrows {
    animation: loader 1.25s infinite;
   transform-origin:center;
   transform-box:fill-box;
  }

  @keyframes loader {
    0% {
      rotate: 0deg;
    }

    100% {
      rotate: 180deg;
    }
  }
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
    <g fill="none" fill-rule="evenodd">
      <path d="M0 0h24v24H0z" />
      <path
        d="M23 14.864C23 17.696 20.737 20 17.956 20c-.11 0-.236 0-.346-.016V20H6.044c-.11 0-.22 0-.33-.016C3.09 19.808 1 17.584 1 14.864c0-2.16 1.304-4.016 3.159-4.784.157-2.512 2.2-4.48 4.698-4.48 .487 0 .959.08 1.399.224h.015A4.993 4.993 0 0 1 14.137 4c2.782 0 5.044 2.304 5.044 5.136 0 .24-.015.48-.062.72C21.35 10.4 23 12.432 23 14.864z"
        fill="#000" fill-rule="nonzero" />
      <path id="circle-arrows"
        d="M14.35 13.98 c-.5 2.07-2.21 3.52-4.37 3.52a4.49 4.49 0 01-3.09-1.24l-.75 .75a0.38 .38 0 01-.27 .12 .38 .38 0 01-.37-.38v-2.62c0-.21 .17-.38 .37-.38h2.63c0.21 0 .38 .17 .38 .38 0 .09-.04 .19-.11 .26l-.81 .8a2.99 2.99 0 004.59-.62c0.15-.23 .22-.45 .32-.69 .02-.08 .08-.13 .17-.13h1.13c0.1 0 .18 .09 .18 .19 0 .01 0 .03 0 .04zm0.15-2.1c0 .2-.17 .37-.37 .37h-2.63a0.38 .38 0 01-.37-.37c0-.1 .03-.2 .1-.27l0.81-.81a3.02 3.02 0 00-2.04-.8c-1.04 0-2.01 .54-2.55 1.43-.15 .23-.22 .45-.32 .69-.02 .08-.08 .13-.17 .13h-1.17a0.19 .19 0 01-.18-.19v-.04c0.5-2.08 2.23-3.52 4.39-3.52 1.15 0 2.27 .46 3.1 1.24l0.76-.75a0.38 .38 0 010.27-.11c0.2 0 .37 .17 .37 .37v2.63z"
        fill="#FFF" fill-rule="nonzero" />
    </g>
  </svg>

The rotate property within the transform shorthand may cause issues in certain Safari/webkit browser versions when applied to SVG elements.

To ensure better cross-browser compatibility, it's recommended to use the verbose legacy notation for rotation:

transform: rotate(180deg)

In addition, consider removing these properties/attributes:

  • border-radius is not applicable to SVG elements
  • fill-rule has no effect unless dealing with overlapping compound path shapes
  • You can simplify the animation to a single state - either 100% or to
  • Certain editors like Figma may add unnecessary bounding box rectangles like
    <path d="M0 0h24v24H0z" />

<svg style="width:240px" viewbox="0 0 24 24" >
  <style>
    #circle-arrows {
      animation: loader 1.25s infinite forwards linear;
    }

    @keyframes loader {
      100% {
        transform: rotate(180deg);
      }
    }
  </style>
  <path d="M23 14.9c0 2.8-2.3 5.1-5 5.1-.2 0-.3 0-.4 0h0-11.6c-.1 0-.2 0-.3 0-2.6-.2-4.7-2.4-4.7-5.1 0-2.2 1.3-4.1 3.2-4.8 .1-2.5 2.2-4.5 4.7-4.5 .4 0 .9 .1 1.4 .2l0 0c0.9-1.1 2.3-1.8 3.8-1.8 2.8 0 5.1 2.3 5.1 5.1 0 .3 0 .5-.1 .8 2.3 .5 3.9 2.5 3.9 5z" />
  <path id="circle-arrows" fill="#fff" transform-origin="center" d="m16.35 12.98c-.5 2.07-2.21 3.52-4.37 3.52a4.49 4... 

For smooth looping animations, consider applying

animation-timing-function: linear
;

You can convert your SVG to a standalone asset (for use in an <img> or CSS background-image) by including the stylesheet directly in the SVG and adding the xmlns namespace.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Toggling reverses multiple CSS keyframe animations

I've been working on a unique animation to switch my website between dark and light mode. The animation is quite complex, so I anticipate that the solution will be equally intricate. Currently, I am toggling between classes, but this approach makes i ...

What is the best way to implement automatic color changing in PHP code?

I have a MySQL table called 'contact number' that contains the field 'c_n'. I need to display data from this field and change the color based on the length of the value. If the field's value is less or more than 11 digits, the colo ...

What are some ways to stop animated scrolling text from unexpectedly resetting in HTML and CSS?

I created this code snippet on CodePen to illustrate my point: https://codepen.io/sakana-boy/pen/wvBedWo .scroll-text { overflow: hidden; position: relative; } .scroll-text * { white-space: pre; transform: translateX(100%); animatio ...

Using External Libraries to Modify the DOM in React - A Comprehensive Guide

Currently, I am in the midst of converting an older BackboneJS app to ReactJS. This application utilizes VexFlow, a JavaScript engine for rendering music notations. One key challenge I've faced is that VexFlow independently renders everything to SVG, ...

What is the best way to complete a CSS animation and load a new URL simultaneously?

I was thinking of incorporating a series of fade-ins, followed by a fade-out, and concluding with the loading of a new page (target=self). After some research online, it appears that CSS animations do not include the functionality to fetch a new URL as the ...

Is there a way to adjust the zoom levels of specific sections on my website when using Ctrl-+ and Ctrl--?

It's interesting how I have split elements of my Dreamweaver web page between the <body> section and the <div class="twoColFixRtHdr"> Dreamweaver template nested within it. This setup causes the two areas to zoom in at different rates when ...

What causes the difference in behavior between absolute positioning in <button> and <div>?

I am noticing that the code below is not positioning my span to the top-left corner of the button as I expected. Can anyone explain why? <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> &l ...

Is there a way to target the mat-icon element using the icon's name in CSS

I have a group of mat-icons that are automatically generated, meaning I cannot assign them ids or classes. The only way to distinguish between them is by their names: <mat-icon role="img">details</mat-icon> <mat-icon role="img ...

How to eliminate the inner padding border within a Material UI Outlined Text Field

I am currently utilizing the Material UI v5 Outlined TextField component to develop a form. In the image below, you can see a white padding border appearing in the TextField. I have created CSS that changes the input field color to yellow when focused. Th ...

Is it possible to have an icon change color in a TableRow column when hovering over any part of that particular row?

I am currently using material-ui version 4.9.5. To illustrate my issue, I have created a simplified example here. I have a Table that is populated with basic JSON data. Each row in the table consists of an icon element along with its corresponding color a ...

When the direction is set to rtl, special characters that are supposed to be at the

When using the direction property for a label with windows style directory paths containing backslashes, I encountered an issue. The purpose of using direction:rtl; was to display the end part (file names) of the path. However, I found that I am getting th ...

Disable toolbar focus in TinyMCE

Is there a method to prevent the appearance of the white square known as "Focus to toolbar" in TinyMCE? Clarification: Upon pressing Alt+F10 in TinyMCE, a white square is outlined around a button on the toolbar. This allows navigation among toolbar butto ...

The ng-style directive is not functioning properly

After selecting a category, I attempted to change the color using "ng-style" in my HTML code. However, it seems that the color change is not taking effect. This is the snippet from my HTML code: <div ng-repeat="item in ListExpense" ng-class-odd="&apos ...

What is the best method for applying margin to an icon within a SASS selector?

I'm trying to figure out how to add a margin right to an icon in my SCSS code, but so far I haven't been able to select it properly despite all the research I've done... Here is my current SCSS code: select{ background-color: hsl(209, 23 ...

What is the best way to add a class to the initial HTML element in my specific scenario?

Currently utilizing the angular framework in my application. Desire to assign a specific class to only the initial element within my ng-repeat iteration. <div class='initialOnly' ng-repeat = 'task in tasks'>{{task.chore}}</di ...

Top/bottom/body script

I could definitely use some assistance in implementing code that involves div elements for a #header, #footer, and #main. I'm a bit unsure of where exactly to insert this code within the existing structure. I have already set up a basic HTML page pair ...

How to change the background color of select options using JQuery

My webpage includes multiple select boxes with different options: <select name="item-0-status" id="id_item-0-status"> <option value="">---------</option> <option value="1">Online</option> <option value="2">Offline</o ...

What causes overflow-x scroll to prevent scrolling to the left unless the initial scroll is to the left?

<div class="row justify-content-center mob-view" > <div class="col-lg-3 col-md-4" *ngFor="let slide of specialization"> <div class="brower-box"> &l ...

Organize icons within a container that spans the entire height

I am looking to organize multiple icons within a container that spans the entire height of the website, rather than just the viewport. Currently, I am only able to achieve the height of the viewport using the following code: .full-container { posit ...

Is it possible to utilize an svg markup element like (g) as the primary element in a React JSX return statement?

I have a desire to accomplish the following: Element Customer / Offspring return ( <Limage> <g id="golf"> <path fill="none" stroke="#fff" stroke-width="4" stroke-linejoin="round" stroke-miterlimit= ...