← Back to the icon library

MOTIVE · ARTICLE

How SVG animation works, and what makes it fast

A bell rings when a reminder is enabled. A check draws itself when a task finishes. Small movements communicate a change in state. Here is how SVG creates them and what to measure when you use many icons.

1. Shapes plus a timeline

SVG describes shapes such as path, circle, and rect with coordinates and attributes. A viewBox="0 0 24 24" defines the internal coordinate system; width and height define the displayed size. That lets you reuse the same geometry at different sizes.

Animation changes the properties of those shapes over time. Set a rotation to 0 degrees at the start, -18 degrees in the middle, and 0 again at the end, and a bell rocks. The browser interpolates between keyframes using your duration and easing. You do not need a separate stored image for every frame.

2. Drawing a check by moving a dash pattern

The check already exists before it appears to draw. stroke-dasharray creates a pattern of strokes and gaps; changing stroke-dashoffset moves the start of that pattern so the line becomes visible.

The example normalizes distance calculations with pathLength="60", then animates dashoffset from 60 to 0. The number 60 is not a count of screen pixels. The base attributes show the finished check, so disabling animation or requesting reduced motion keeps its meaning visible. Paste the code into HTML to try it.

MDN · stroke-dashoffsetMDN · pathLength

A working line-drawing example

The same SVG and CSS appear below. Pause or resume the loop; reduced motion displays the completed check.

<svg xmlns="http://www.w3.org/2000/svg"
     width="64" height="64" viewBox="0 0 24 24"
     fill="none" stroke="currentColor" stroke-width="2"
     stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
  <style>
    .motive-draw { animation: motive-draw 1.8s ease-in-out infinite; }
    @keyframes motive-draw {
      0% { stroke-dashoffset: 60; }
      60%, 100% { stroke-dashoffset: 0; }
    }
    @media (prefers-reduced-motion: reduce) {
      .motive-draw { animation: none; }
    }
  </style>
  <path class="motive-draw" d="m6 12 4 4 8-8"
        pathLength="60" stroke-dasharray="60" stroke-dashoffset="0" />
</svg>

3. CSS and the Web Animations API

CSS @keyframes often suffices for a predefined loop or a single play. Downloaded Motive SVGs include their CSS and need no animation library. A page cannot directly select the internal elements of an SVG embedded as an img; consider inline SVG if you need to interact with individual shapes.

The Web Animations API provides playback controls for an editor: play, pause, and seeking. Motive generates preview keyframes and exported CSS from the same motion model. It uses browser animation playback rather than changing React state every frame. Choosing CSS or JavaScript alone does not determine rendering performance.

MDN · Web Animations API

4. An SVG extension does not guarantee low cost

Transfer size and the cost of playback are separate concerns. A few simple shapes can be compact, while complex paths, filters, and many DOM elements increase work. SVG is not always smaller than GIF and does not guarantee a fixed frame rate on every device.

A browser updates the screen with the necessary style, layout, paint, and compositing work. Animated properties, drawing area, and the number of simultaneous animations matter. Start by considering transform and opacity, then check actual compositing behavior in the target SVG scene and browser.

4. An SVG extension does not guarantee low cost
EffectTypical propertiesWhat to inspect
Rotation, movement, scale, fadingtransform, opacityCompositing may help, but GPU execution or skipping paint is not guaranteed.
Line drawing and shape changesstroke-dashoffset, dInspect repainting costs. Several complex animated paths can add substantial work.
Blur, shadows, many shapesfilter, shape count and drawing areaReduce filter bounds and shape count, then compare paint time and memory.

web.dev · High-performance CSS animations

5. Before adding motion to your interface

  • Play short success or error feedback when needed. Decide whether a continuous loop serves a purpose.
  • Use IntersectionObserver to stop offscreen loops in long lists, and check behavior when the tab is hidden. Motive plays only catalog cards that are in view.
  • Respect prefers-reduced-motion: reduce and keep the static state meaningful. Use aria-hidden for decoration and appropriate alternative text for informative images.
  • Reserve space with width and height. Repeated inline SVGs need nonconflicting IDs for titles, masks, and gradients.
  • Do not add will-change to every icon preemptively. Measure a real issue, apply it only where needed, and compare the result.

MDN · prefers-reduced-motion

6. Measure under the same conditions

  1. Keep the icon, size, motion, and duration constant. Compare simultaneous counts such as 1, 20, and 100, and record both the visible count and total count.
  2. Use a build similar to production. Inspect compressed transfer size and request count in Network. File size alone does not measure playback cost.
  3. Record playback and scrolling in the DevTools Performance panel. Compare Layout, Paint, and delayed frames. At 60Hz a frame lasts about 16.7ms, which is the budget for the entire page. Do not promise an FPS without measurements.
  4. Try a real mobile device too. Check reduced motion, offscreen icons, hidden tabs, and finite repetition. Record the device, browser, and conditions so someone else can reproduce your observations.

Official references