mattstuehler mattstuehler - 2 months ago 15
CSS Question

Is it possible to animate an SVG background on a DOM element with CSS?

I have used SMIL to animate an SVG image, then used that image as the background for a DOM element (e.g., a

button
).

For example, this SVG image (http://mattstuehler.com/spinner.svg)

<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 40 40">
<g fill="none" stroke="#1e81cc" stroke-width="4">
<circle cx="50%" cy="50%" r="18" stroke-opacity="0.3"/>
<path d="M20,2 A18,18 0 0,1 38,20">
<animateTransform attributeName="transform" type="rotate" from="0 20 20" to="360 20 20" dur="1s" repeatCount="indefinite"/>
</path>
</g>
</svg>


However, now that SMIL is being deprecated, how would you do this with only CSS?

Thanks in advance!



button {
width: 200px;
height: 60px;
background-color: #eee;
background-image: url(http://mattstuehler.com/spinner.svg);
background-repeat: no-repeat;
background-position: center center;
background-size: 50px 50px;
border: none;
-webkit-appearance: none;
}

<button>Hello</button>




Answer

Update:

Chrome have suspended deprecation of SMIL for now. More here


One way could be to use CSS animations. Animate the path element and fix the transform-origin at the center of the spinner.

Since we can have a <style> tag within an SVG element, we embed this animation in the SVG itself.

CSS Animation / SVG:

<svg height="40" viewbox="0 0 40 40" width="40" xmlns="http://www.w3.org/2000/svg">
  <style>
    path {
      -webkit-animation: rotate 1s linear infinite;
      -moz-animation: rotate 1s linear infinite;
      animation: rotate 1s linear infinite;
      transform-origin: 20px 20px;
    }
    @-webkit-keyframes rotate {
      100% {
        transform: rotate(360deg)
      }
    }
    @keyframes rotate {
      100% {
        transform: rotate(360deg)
      }
    }
  </style>
  <g fill="none" stroke="#1e81cc" stroke-width="4">
    <circle cx="50%" cy="50%" r="18" stroke-opacity="0.3"></circle>
    <path d="M20,2 A18,18 0 0,1 38,20"></path>
  </g>
</svg>

Using the above SVG as a background:

button {
  width: 200px;
  height: 60px;
  background-color: #eee;
  background-image: url(https://dl.dropboxusercontent.com/s/8j3gd6jfujxz2xg/spinner.svg);
  background-repeat: no-repeat;
  background-position: center center;
  background-size: 50px 50px;
  border: none;
}
<button>Hello</button>

Note:
Some browsers may render animated SVGs as a static image when used as a background. Refers to both the CSS method and the SMIL in the question.
Works fine on Chrome/Opera. FF displayed this as a static image.