Day 10: How to Animate an SVG with CSS

You can move some SVG properties to CSS and even animate them with CSS keyframes. In this example, we create a spinning windmill.

Draw the head of the windmill

Let’s start by composing the windmill’s head. Thanks to its central symmetry, we can define a single arm and reuse this element with a rotation.

The path of this arm also covers something we will cover later: a cubic bezier curve. The path segment starting with the letter C draws the bottom round part of this arm. We will cover curves in detail in upcoming chapters.

-100, -100
-7, -20 -7, -10 7, -10 7, -20 2, -80 -2, -80 -7, -20 -7, -10 7, -10 7, -20 2, -80 -2, -80
200, 200
<svg
  width="200"
  height="200"
  viewBox="-100 -100 200 200"
>
  <path 
    id="arm" 
    d="
      M -7 -20 
      C -7 -10 7 -10 7 -20 
      L 2 -80 
      L -2 -80" 
  />
</svg>

To finish the head of the windmill, we reuse the same arm element with a rotation and add a circle to the middle.

-100, -100
0, 0 -7, -20 -7, -10 7, -10 7, -20 2, -80 -2, -80 0, 0 -7, -20 -7, -10 7, -10 7, -20 2, -80 -2, -80
200, 200
<svg
  width="200"
  height="200"
  viewBox="-100 -100 200 200"
>
  <circle r="8" />

  <path 
    id="arm" 
    d="
      M -7 -20 
      C -7 -10 7 -10 7 -20 
      L 2 -80 
      L -2 -80" 
  />

  <use 
    href="#arm"
    transform="rotate(+120)" />

  <use 
    href="#arm" 
    transform="rotate(-120)" />
</svg>

Finish the windmill and add CSS animation

To finish the windmill, we add a stand, and wrap the head of the windmill into two group elements.

The outer group element moves the head of the windmill into the correct position. We translate the head by -50 units.

We assign the ID windmill-head to the inner group and set a keyframe animation in CSS that rotates the head. Note that when we set the rotation in CSS, we need to add the unit of measurement.

<svg
  width="200"
  height="400"
  viewBox="-100 -200 200 400"
  fill="rgba(0, 0, 0, 0.5)"
>
  <g transform="translate(0, -50)">
    <g id="windmill-head">
      <circle r="8"></circle>

      <path id="arm" d="M -7 -20 C -7 -10 7 -10 7 -20 L 2 -80 L -2 -80" />
      <use href="#arm" transform="rotate(+120)" />
      <use href="#arm" transform="rotate(-120)" />
    </g>
  </g>

  <path d="M -7 100 L 7 100 L 3 -35 L -3 -35" />
</svg>
<style>
  #windmill-head {
    animation-name: rotate;
    animation-duration: 4s;
    animation-iteration-count: infinite;
    animation-timing-function: linear;
  }

  @keyframes rotate {
    from {
      transform: rotate(0deg);
    }
    to {
      transform: rotate(360deg);
    }
  }
</style>