Launch Studio
Animation & Motion Guide

How to Animate SVG with CSS: Keyframes, Stroke & Data URIs

Updated October 2026 • Frontend Performance & Motion Series

Scalable Vector Graphics (SVG) combined with CSS animation unlock interactive UI micro-interactions, responsive spinners, and smooth line-drawing sequences without the heavy payload of video or GIF files. However, animating SVGs in web browsers involves distinct architectural boundaries—especially when deciding between inline <svg> elements, CSS mask-image, and URL-encoded background-image Data URIs.

1. Three Methods of Animating SVG in Web Applications

Before writing keyframe rules, frontend engineers must choose the right rendering context for their animated vectors. Each approach has unique browser rendering characteristics:

MethodTarget ElementCan Animate Internal Paths?Best Use Case
Inline SVG<path>, <circle>Yes (Full CSS control)Complex morphs, path drawing, interactive hover states
CSS Mask-ImageParent containerContainer-level onlyPulsing icons, color transitions, rotating indicators
CSS Background-ImageParent containerVia SMIL or ContainerInfinite spinners, drifting background grids & textures

2. The SVG Line-Drawing Animation Technique

The classic vector drawing effect—where an icon appears to draw itself onto the screen—relies on two foundational SVG stroke properties: stroke-dasharray and stroke-dashoffset.

By setting both the dash length and the dash offset equal to the path's total length, the gap completely hides the path. Animating stroke-dashoffset to zero draws the stroke smoothly into view:

/* 1. Define the initial stroke setup */
.animated-icon-path {
  stroke: #38bdf8;
  stroke-width: 2;
  fill: transparent;
  stroke-dasharray: 280;
  stroke-dashoffset: 280;
  animation: drawStroke 1.6s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}

/* 2. Keyframes transition the offset to reveal the path */
@keyframes drawStroke {
  to {
    stroke-dashoffset: 0;
  }
}

Calculating Path Length: In production JavaScript, calculate the exact path length using the native DOM method:

const path = document.querySelector('.my-svg-path');
const totalLength = path.getTotalLength();
path.style.strokeDasharray = totalLength;
path.style.strokeDashoffset = totalLength;

3. Can You Animate a CSS Background Data URI?

A frequent question among frontend developers is: Can external CSS keyframes target individual <path> elements inside a background-image: url('data:image/svg+xml,...') declaration?

The answer is no. When an SVG is embedded as an image via a Data URI or an <img> tag, modern browsers place it in an isolated image sandbox. External stylesheets and JavaScript on the host page cannot access the internal DOM tree of the SVG.

However, you have two high-performance alternatives for animated Data URIs:

Strategy A: Animate the Container via Hardware-Accelerated CSS

If the entire icon rotates, pulses, or translates (like a loading spinner or floating badge), encode the static SVG using SVG2CSS, set it as a background, and animate the container's CSS transform:

.loading-spinner {
  width: 24px;
  height: 24px;
  background-image: url('data:image/svg+xml,%3Csvg xmlns=\'http://www.w3.org/2000/svg\' viewBox=\'0 0 24 24\' fill=\'none\' stroke=\'%2338bdf8\' stroke-width=\'2.5\'%3E%3Cpath d=\'M12 2 A 10 10 0 0 1 22 12\'/%3E%3C/svg%3E');
  background-size: contain;
  background-repeat: no-repeat;
  animation: spin 0.8s linear infinite;
  will-change: transform;
}

@keyframes spin {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

Strategy B: Embed SMIL or Embedded CSS Inside the SVG Markup

SVGs support internal <style> tags and native SMIL (Synchronized Multimedia Integration Language) elements like <animateTransform> directly inside the vector XML. Because the animation is self-contained within the SVG file itself, browsers will execute the animation even when rendered inside a CSS background-image:

/* Self-animating Data URI with embedded SMIL */
.self-pulsing-badge {
  background-image: url('data:image/svg+xml,%3Csvg xmlns=\'http://www.w3.org/2000/svg\' viewBox=\'0 0 32 32\'%3E%3Ccircle cx=\'16\' cy=\'16\' r=\'10\' fill=\'%2338bdf8\'%3E%3Canimate attributeName=\'opacity\' values=\'1;0.3;1\' dur=\'2s\' repeatCount=\'indefinite\'/%3E%3C/circle%3E%3C/svg%3E');
}

4. Transform Origin Differences: HTML vs SVG

One of the most notorious gotchas when animating SVG in CSS is the behavior of transform-origin:

To ensure predictable rotation around the element's own center across modern browsers, explicitly declare:

.rotating-gear {
  transform-box: fill-box;
  transform-origin: center;
  animation: spinGear 3s linear infinite;
}

5. GPU Acceleration & Performance Best Practices

Animating complex vector shapes can trigger expensive layout re-calculations if done incorrectly. Follow these engineering guidelines to guarantee a solid 60fps frame rate:

Convert Vectors for High-Performance CSS Animation

Clean your SVG markup with SVGO, strip redundant groups, and generate clean URL-encoded CSS.

Open SVG to CSS Studio