Animated SVG favicons
When it comes to animating SVGs, there're three options: using CSS, JS, or SMIL. Each comes with its own pros and cons, whose discussion is beyond the scope of this article, but Sara Soueidan has a great article on the topic. In this post, I add a repeating shrink animation to a circle with all three methods, and then try to use these SVGs as favicons.
Animating SVG with CSS
Here's an example of animating an SVG with CSS based on the animation
and the transform
properties. I scale the circle from the center and repeat the animation forever:
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<style>
svg {
max-width: 100px;
}
circle {
display: block;
animation: 2s linear infinite both circle-animation;
transform-origin: 50% 50%;
}
@keyframes circle-animation {
0% {
transform: scale(1);
}
100% {
transform: scale(0);
}
}
</style>
<circle fill="red" cx="50" cy="50" r="45" />
</svg>
Animating SVG with JS
The SVG <script>
tag allows to add scripts to an SVG document. It has some subtle differences to the regular HTML <script>
, for example, it uses the href
instead of the src
attribute, but above all it's important to know that any functions defined within any <script>
tag have a global scope across the entire current document. Below, you can see an SVG script used to reduce the radius of the circle until it's equal to zero, then reset it to the initial value, and finally repeat this forever.
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<circle fill="blue" cx="50" cy="50" r="45" />
<script type="text/javascript">
<![CDATA[ const circle = document.querySelector('circle'); let r = 45; const
animate = () => { circle.setAttribute('r', r--); if (r === 0) { r = 45; }
requestAnimationFrame(animate); }; requestAnimationFrame(animate); ]]>
</script>
</svg>
Animating SVG with SMIL
The last example uses SMIL, where, via the <animate>
tag inside of the <circle>
tag, I declaratively describe that I want to animate the circle's r
attribute (that determines the radius) and repeat it indefinitely.
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<circle fill="green" cx="50" cy="50" r="45">
<animate
attributeName="r"
from="45"
to="0"
dur="2s"
repeatCount="indefinite"
/>
</circle>
</svg>
Using Animated SVGs as Images
Before using animated SVGs as favicons, I want to briefly discuss how you can use each of the three examples on a website. Again there're three options: referenced via the src
attribute of an <img>
tag, in an <iframe>
, or inlined in the main document. Again, SVG scripts have access to the global scope, so they should definitely be used with care. Some user agents, for example, Google Chrome, don't run scripts for SVGs in <img>
. The Glitch embedded below shows all variants in action. My recommendation would be to stick with CSS animations whenever you can, since it's the most compatible and future-proof variant.
Using Animated SVGs as Favicons
Since crbug.com/294179 is fixed, Chrome finally supports SVG favicons, alongside many other browsers. I have recently successfully experimented with prefers-color-scheme
in SVG favicons, so I wanted to see if animated SVGs work, too. Long story short, it seems only Firefox supports them at the time of writing, and only favicons that are animated with either CSS or JS. You can see this working in Firefox in the screencast embedded below. If you open my Glitch demo in a standalone window, you can test this yourself with the radio buttons at the top.
Should you use this in practice? Probably not, since it can be really distracting. It might be useful as a progressive enhancement to show activity during a short period of time, for example, while a web application is busy with processing data. Before considering to use this, I would definitely recommend taking the user's prefers-reduced-motion
preferences into account.