Home » Technical Posts » Using SVG Animation in WordPress

Using SVG Animation in WordPress

Updated:

Since I originally wrote this post, browsers have updated and so has the CSS specs. With the addition of the transform-box CSS property, you can now define the layout box that the transform and transform-origin properties relate to.

Earlier this year, I wrote a post on how to add an SVG logo to WordPress.

SVGs (stands for (Scalable Vector Graphics) are awesome. They’re lightweight, crisp, and sharp at any size – something you just can’t get with a JPG or PNG file.

Browser support is very good with a few exceptions. Check here for the latest browser support issues regarding SVG.

SVG files can be added to a WordPress site as either embedded images, CSS backgrounds or inline graphics. The latter is what I’ll focus on in this post.

Inline Graphics

If we want to style our SVG with CSS, we’ll need to insert the SVG code directly into our HTML as an inline graphic.

When designing the logo for my upcoming podcast series Rethink.fm – I wanted to animate the logo by turning the cog wheels.

SVG file not found: /home/1104999.cloudwaysapps.com/dymtrapngx/public_html/wp-content/themes/astra-child/images/rethinkfm-logo.svg

Animating SVG in WordPress content

I’ll walk you through how I inserted the SVG I created below into this post. Then animate it with CSS to make the three cog wheels spin, with one going counter-clockwise for a realistic effect.

SVG file not found: /home/1104999.cloudwaysapps.com/dymtrapngx/public_html/wp-content/themes/astra-child/images/cog-wheels.svg

Step 1. Create the SVG file

I created this in Affinity Designer (my personal favorite – currently only available for Mac… Windows version is in beta). You can use any vector based design program (like Adobe Illustrator). Once I created it, I exported it as a SVG file.

Then I edited the SVG file and added some classes so I could target them with CSS.

Step 2. Embed the SVG file into your post.

Here are two approaches I found to add SVG files to your WordPress content and style them with CSS.

  1. Upload the SVG files to a folder on your host server and then embed via a shortcode through a simple plugin.
  2. Use one of several plugin in the WordPress repository to enable uploading SVG files into the WordPress media library. This comes with security concerns, if users will be uploading SVG files to the website. SVG files are code and given that, you need to take precautions to protect what is being uploaded to your database.

For this demo, I’ll go with option 1.

I wrote a simple plugin for option 1, so that I can use a shortcode to insert my SVG files into the content. You can find it here on Github.

Remember, plugins are for features and themes are for styling and presentation. Since option 1 is a new feature, I’ll be using a plugin.

With my plugin installed and activated, all I need to do is upload my SVG to the images folder in my child theme and then insert the shortcode into the post.

[insert-svg-code file="cog-wheels" class="cog-wheels"]

Step 3. Add animation

I’m making use of the CSS3 @keyframes rule to specify the animation code. I created a spin and a spin-reverse rule using the transform rule set to rotate(360deg) and rotate(-360deg) for the reverse spin. I added both the transform-origin and the transform-box rules.

  transform-origin: 50% 50%;
  transform-box: fill-box;

You can see the code in action here on CodePen.

See the Pen SVG Cog Wheels Rotating – percentages by Jackie D’Elia (@jdelia) on CodePen.

The problem with this method is it won’t work in earlier versions of Firefox.

Firefox and transform-origin using percentages

(Sorry if this is making you dizzy!)

One issue I came across is in Firefox using transform-origin with percentages before the transform-box rule was supported. It worked as expected in Chrome and Safari. Firefox did not support percentages, so you ended up with an animation based on the center of the entire SVG and not each element. The current version of Firefox works fine, now that I added the transform-box: fill-box rule.

Animation result as expected
Using percentages for transform-origin. Animation as expected.
Animation result in Firefox
Using percentages for transform-origin. Animation in earlier versions of Firefox.

How to solve the rotation issue in earlier versions of Firefox

Use pixels to target the center of each element so they rotate around that center point. To get those coordinates, I added a circle around each cog wheel in my SVG source file before exporting to SVG.

Adding a circle for each cog
Adding a circle for each cog before exporting SVG file.

The edited SVG file looks like this after I’ve added my classes and set the fill for the circles to transparent:

<svg width="100%" height="100%" viewBox="0 0 600 600" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;">
<rect x="-152" y="-117" width="882" height="819" fill="#ebebeb"/>
<g>
<circle id="circle-yellow" cx="393.785" cy="409.5" r="100" fill="transparent"/>
<g>
<path class="cog-yellow" d="M378.75,310.637c-6.476,0.985 -12.839,2.603 -18.999,4.832l0.962,15.729c-5.814,2.455 -11.337,5.551 -16.466,9.229l-12.915,-9.028c-5.115,4.091 -9.817,8.675 -14.036,13.685l8.696,13.14c-3.807,5.034 -7.042,10.476 -9.644,16.226l-15.699,-1.361c-2.385,6.101 -4.165,12.421 -5.314,18.869l14.102,7.032c-0.781,6.263 -0.861,12.593 -0.24,18.874l-14.276,6.671c0.985,6.476 2.604,12.839 4.833,18.998l15.728,-0.961c2.456,5.814 5.551,11.336 9.23,16.465l-9.028,12.915c4.091,5.116 8.674,9.818 13.684,14.037l13.141,-8.697c5.033,3.807 10.475,7.042 16.225,9.645l-1.36,15.699c6.1,2.385 12.42,4.164 18.869,5.313l7.031,-14.101c6.263,0.78 12.594,0.861 18.875,0.239l6.67,14.276c6.476,-0.985 12.84,-2.603 18.999,-4.832l-0.962,-15.729c5.814,-2.455 11.337,-5.551 16.466,-9.229l12.915,9.028c5.116,-4.091 9.817,-8.675 14.036,-13.685l-8.696,-13.14c3.807,-5.034 7.042,-10.476 9.645,-16.226l15.698,1.361c2.385,-6.101 4.165,-12.421 5.314,-18.869l-14.102,-7.032c0.781,-6.263 0.861,-12.593 0.24,-18.874l14.276,-6.671c-0.985,-6.476 -2.604,-12.839 -4.833,-18.998l-15.728,0.961c-2.456,-5.814 -5.551,-11.336 -9.23,-16.465l9.028,-12.915c-4.091,-5.116 -8.674,-9.818 -13.684,-14.037l-13.14,8.697c-5.034,-3.807 -10.476,-7.042 -16.226,-9.645l1.361,-15.699c-6.101,-2.385 -12.421,-4.164 -18.87,-5.313l-7.031,14.101c-6.263,-0.78 -12.594,-0.861 -18.875,-0.239l-6.67,-14.276ZM388.854,390.117c10.698,-2.721 21.592,3.755 24.313,14.452c2.722,10.698 -3.754,21.592 -14.452,24.314c-10.697,2.721 -21.592,-3.755 -24.313,-14.452c-2.721,-10.698 3.754,-21.592 14.452,-24.314Z" fill="#fcbe06"/>
</g>
<circle id="circle-blue" cx="306.785" cy="190.5" r="100" fill="transparent"/>
<g>
<path class="cog-blue" d="M291.75,91.637c-6.476,0.985 -12.839,2.603 -18.999,4.832l0.962,15.729c-5.814,2.455 -11.337,5.551 -16.466,9.229l-12.915,-9.028c-5.115,4.091 -9.817,8.675 -14.036,13.685l8.696,13.14c-3.807,5.034 -7.042,10.476 -9.644,16.226l-15.699,-1.361c-2.385,6.101 -4.165,12.421 -5.314,18.869l14.102,7.032c-0.781,6.263 -0.861,12.593 -0.24,18.874l-14.276,6.671c0.985,6.476 2.604,12.839 4.833,18.998l15.728,-0.961c2.456,5.814 5.551,11.336 9.23,16.465l-9.028,12.915c4.091,5.116 8.674,9.818 13.684,14.037l13.141,-8.697c5.033,3.807 10.475,7.042 16.225,9.645l-1.36,15.699c6.1,2.385 12.42,4.164 18.869,5.313l7.031,-14.101c6.263,0.78 12.594,0.861 18.875,0.239l6.67,14.276c6.476,-0.985 12.84,-2.603 18.999,-4.832l-0.962,-15.729c5.814,-2.455 11.337,-5.551 16.466,-9.229l12.915,9.028c5.116,-4.091 9.817,-8.675 14.036,-13.685l-8.696,-13.14c3.807,-5.034 7.042,-10.476 9.645,-16.226l15.698,1.361c2.385,-6.101 4.165,-12.421 5.314,-18.869l-14.102,-7.032c0.781,-6.263 0.861,-12.593 0.24,-18.874l14.276,-6.671c-0.985,-6.476 -2.604,-12.839 -4.833,-18.998l-15.728,0.961c-2.456,-5.814 -5.551,-11.336 -9.23,-16.465l9.028,-12.915c-4.091,-5.116 -8.674,-9.818 -13.684,-14.037l-13.14,8.697c-5.034,-3.807 -10.476,-7.042 -16.226,-9.645l1.361,-15.699c-6.101,-2.385 -12.421,-4.164 -18.87,-5.313l-7.031,14.101c-6.263,-0.78 -12.594,-0.861 -18.875,-0.239l-6.67,-14.276ZM301.854,171.117c10.698,-2.721 21.592,3.755 24.313,14.452c2.722,10.698 -3.754,21.592 -14.452,24.314c-10.697,2.721 -21.592,-3.755 -24.313,-14.452c-2.721,-10.698 3.754,-21.592 14.452,-24.314Z" fill="#006fa2"/>
</g>
<circle id="circle-red" cx="207.352" cy="357.835" r="100" fill="transparent"/>
<g>
<path class="cog-red" d="M217.154,258.316c-6.519,-0.642 -13.085,-0.642 -19.604,0l-2.945,15.48c-6.24,0.947 -12.355,2.585 -18.233,4.886l-10.291,-11.933c-5.966,2.703 -11.652,5.986 -16.977,9.801l5.189,14.879c-4.93,3.94 -9.407,8.416 -13.347,13.347l-14.879,-5.189c-3.815,5.325 -7.098,11.011 -9.801,16.977l11.933,10.291c-2.3,5.877 -3.939,11.993 -4.886,18.233l-15.479,2.945c-0.642,6.519 -0.642,13.085 0,19.604l15.479,2.945c0.947,6.24 2.586,12.356 4.886,18.233l-11.933,10.291c2.703,5.966 5.986,11.652 9.801,16.977l14.879,-5.189c3.94,4.931 8.417,9.407 13.347,13.347l-5.189,14.879c5.325,3.815 11.011,7.098 16.977,9.801l10.291,-11.933c5.878,2.301 11.993,3.939 18.233,4.886l2.945,15.479c6.519,0.642 13.085,0.642 19.604,0l2.945,-15.479c6.24,-0.947 12.356,-2.585 18.233,-4.886l10.291,11.933c5.966,-2.703 11.653,-5.986 16.977,-9.801l-5.189,-14.879c4.931,-3.94 9.407,-8.416 13.347,-13.347l14.879,5.189c3.815,-5.325 7.098,-11.011 9.802,-16.977l-11.934,-10.291c2.301,-5.877 3.939,-11.993 4.886,-18.233l15.48,-2.945c0.642,-6.519 0.642,-13.085 0,-19.604l-15.48,-2.945c-0.947,-6.24 -2.585,-12.356 -4.886,-18.233l11.934,-10.291c-2.704,-5.966 -5.987,-11.652 -9.802,-16.977l-14.879,5.189c-3.94,-4.931 -8.416,-9.407 -13.347,-13.347l5.189,-14.879c-5.324,-3.815 -11.011,-7.098 -16.977,-9.801l-10.291,11.933c-5.877,-2.301 -11.993,-3.939 -18.233,-4.886l-2.945,-15.48ZM207.352,337.835c11.038,0 20,8.962 20,20c0,11.038 -8.962,20 -20,20c-11.038,0 -20,-8.962 -20,-20c0,-11.038 8.962,-20 20,-20Z" fill="#e5554e"/>
</g>
</g>
</svg>

Notice in the SVG code, the cx and cy values for each cog circle. That’s the center point for each circle which happens to be the center point for each cog, since each cog fits perfectly in each circle. Now I can use those coordinates to specify the center in my transforms-origin rule for each cog.

Have a look at the CSS below.

/* Wrap the SVG in a div */
.cog-wheels {
margin: 2% auto;
width: 300px;
height: 300px;
}
/*Rotate cogs*/
svg .cog-blue {
transform-origin: 306.785px 190.5px;
animation: spin 10s linear infinite;
animation-delay: 0.8s;
}
svg .cog-red {
transform-origin: 207.352px 357.835px;
animation: spin-reverse 10s linear infinite;
animation-delay: 0.8s;
}
svg .cog-yellow {
transform-origin: 393.785px 409.5px;
animation: spin 10s linear infinite;
animation-delay: 0.8s;
}
@keyframes spin {
100% {
-moz-transform: rotate(360deg);
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@keyframes spin-reverse {
100% {
-moz-transform: rotate(-360deg);
-webkit-transform: rotate(-360deg);
transform: rotate(-360deg);
}
}

Wrap it up

It was a challenge working on this solution and I’ve really enjoyed adding animation to SVG. In a future post, I’ll share with you how I add animation to other CSS elements.

Here is the final code with the Firefox fix on CodePen.

See the Pen SVG Cog Wheels Rotating – Firefox fix

Scroll to Top