Now that SMIL is dying I want to convert my simple animated SVGs to using CSS Animations, but I am not super sure how to do the mapping. In this specific svg there are two animation elements.
#embedded {
color: red;
}
<svg id="embedded" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid">
<circle cx="50" cy="50" r="45" stroke="rgba(43,43,43,0.3)" fill="none" stroke-width="10" stroke-linecap="round"/>
<circle cx="50" cy="50" r="45" stroke="currentColor" fill="none" stroke-width="6" stroke-linecap="round">
<animate attributeName="stroke-dashoffset" dur="2s" repeatCount="indefinite" from="0" to="502"/>
<animate attributeName="stroke-dasharray" dur="2s" repeatCount="indefinite" values="150.6 100.4;1 250;150.6 100.4"/>
</circle>
</svg>
While I seemingly started out fine with these css rules I quickly got stuck
stroke-dasharray: 150.6 100.4 1 250 150.6 100.4;
animation-duration: 2s;
animation-iteration-count: infinite;
stroke-dashoffset: ?;
What would a complete mapping be like? Is it possible at all? Sara Soueidan says not all animations are possible using CSS that are possible using SMIL.
The below is how you'd convert that SMIL animation into its equivalent CSS animation:
animate
tags have the dur="2s"
and so the CSS animation's duration (animation-duration
) would also be 2s
. You can either specify this value using the long-hand property or using the short-hand property like in the below snippet.calcMode
attribute specified for your animate
element and so the interpolation mode is linear
. Since the interpolation mode is linear
, the animation-timing-function
will also be linear
.repeatCount
is indefinite
and so the animation-iteration-count
will be infinite
.stroke-dashoffset
, the animation has only a from (0%) and a to (100%) value. So, in the CSS animation's keyframes, we specify the stroke-dashoffset
as 0
(from
value) at 0%
and as 502
(to
value) at 100%
.stroke-dasharray
, the animation makes use of values instead of just from
and to
. In this case, there are three semi-colon separated values and so the first value from the list is given within the 0%
keyframe , the second value from the list is given at 50%
keyframe and the last is given within the 100%
keyframe selector.#embedded, #embedded2 {
color: red;
width: 200px;
height: 200px;
}
#embedded circle#animated {
animation: demo 2s infinite linear;
}
@keyframes demo {
0% {
stroke-dashoffset: 0;
stroke-dasharray: 150.6 100.4;
}
50% {
stroke-dasharray: 1 250;
}
100% {
stroke-dashoffset: 502;
stroke-dasharray: 150.6 100.4;
}
}
<svg id="embedded" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid">
<circle cx="50" cy="50" r="45" stroke="rgba(43,43,43,0.3)" fill="none" stroke-width="10" stroke-linecap="round" />
<circle cx="50" cy="50" r="45" stroke="currentColor" fill="none" stroke-width="6" stroke-linecap="round" id="animated">
</circle>
</svg>
<svg id="embedded2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid">
<circle cx="50" cy="50" r="45" stroke="rgba(43,43,43,0.3)" fill="none" stroke-width="10" stroke-linecap="round" />
<circle cx="50" cy="50" r="45" stroke="currentColor" fill="none" stroke-width="6" stroke-linecap="round">
<animate attributeName="stroke-dashoffset" dur="2s" repeatCount="indefinite" from="0" to="502" />
<animate attributeName="stroke-dasharray" dur="2s" repeatCount="indefinite" values="150.6 100.4;1 250;150.6 100.4" />
</circle>
</svg>