SVG Animation
The animate and animateTransform elements animate attributes and transforms declaratively, controlled by attributeName, dur, and repeatCount, with no JavaScript required.
Animating SVG Declaratively with SMIL
SVG has built-in animation elements - <animate>, <animateTransform>, and <animateMotion> - that change an attribute's value over time without any JavaScript. You place one inside the shape it animates (or link it with the href attribute), and the browser handles the interpolation, timing, and repetition automatically. This declarative system is part of SMIL and is supported in every modern browser.
<animate>: Animating a Plain Attribute
<animate> changes any animatable presentation attribute, named in attributeName, such as cx, r, opacity, or fill. Use from and to for a simple two-point animation, or values for a semicolon-separated list of stops. dur sets how long one cycle takes (e.g. "2s"), and repeatCount controls how many times it plays - a number, or "indefinite" to loop forever.
Example
<!DOCTYPE html>
<html>
<body>
<svg viewBox="0 0 120 120">
<circle cx="60" cy="60" r="20" fill="#e74c3c">
<animate attributeName="r" from="20" to="40"
dur="1.5s" repeatCount="indefinite" />
<animate attributeName="opacity" values="1;0.3;1"
dur="1.5s" repeatCount="indefinite" />
</circle>
</svg>
</body>
</html><animateTransform>: Animating the transform Attribute
Because transform is not a simple numeric attribute, animating rotation, scale, translation, or skew requires <animateTransform> instead of <animate>. Its type attribute picks which transform function to animate - "rotate", "scale", "translate", "skewX", or "skewY" - and from/to must supply the same number of arguments that function normally takes.
Example
<!DOCTYPE html>
<html>
<body>
<svg viewBox="0 0 120 120">
<rect x="50" y="50" width="20" height="20" fill="#2980b9">
<animateTransform attributeName="transform" type="rotate"
from="0 60 60" to="360 60 60"
dur="2s" repeatCount="indefinite" />
</rect>
</svg>
</body>
</html>Controlling Timing: begin, fill, and Easing
begin delays the start of an animation ("1s") or ties it to an event ("click", or "otherShape.end" to chain after another animation finishes). fill="freeze" holds the final value once the animation ends instead of snapping back to the original attribute (the default, fill="remove"). For non-linear easing, set calcMode="spline", supply keyTimes to mark when each value in the values list should be reached, and keySplines to define the cubic-bezier easing between each pair of keyframes.
Example
<!DOCTYPE html>
<html>
<body>
<svg viewBox="0 0 120 40">
<circle cx="10" cy="20" r="8" fill="#27ae60">
<animate attributeName="cx" values="10;110;10"
keyTimes="0;0.5;1" calcMode="spline"
keySplines="0.42 0 0.58 1; 0.42 0 0.58 1"
dur="3s" begin="click" fill="freeze"
repeatCount="indefinite" />
</circle>
</svg>
</body>
</html>- repeatCount="indefinite" loops forever; a plain number like repeatCount="3" stops after that many cycles.
- fill="freeze" keeps the last animated value; fill="remove" (the default) snaps back to the pre-animation value the instant the animation ends.
- additive="sum" on <animateTransform> lets a rotation stack on top of an existing transform instead of replacing it.
- begin accepts event-based triggers such as begin="click" or begin="myAnim.end+0.5s" to chain animations together.
- Because SMIL animation runs on the browser's rendering engine declaratively, it can be smoother than JavaScript-driven animation for simple, self-contained loops.
Exercise: SVG Animation
Which SMIL element animates a single presentation attribute, like smoothly changing a circle's radius over time?