TutorialMay 2026 · 11 min read

How to Animate SVG Paths with CSS and SMIL

SVG paths are the most powerful shape primitive in the format — and also the most animatable. This guide covers every major technique: draw-on strokes, path morphing, motion paths, and how to automate it all with a visual editor.

What Is SVG Path Animation?

An SVG path is defined by a d attribute containing a series of move, line, curve, and arc commands. Because paths are mathematical, you can animate nearly every visual property — stroke width, stroke color, stroke offset (the famous draw-on effect), fill color, and even the shape itself via morphing.

The three main approaches to SVG path animation are:

  • CSS keyframes: Animates stroke, opacity, transform, and fill on any path element.
  • SMIL <animate>: Native SVG animation that lives inside the SVG markup — works without a stylesheet.
  • JavaScript (GSAP / anime.js): Full control including path morphing, stagger, and scroll-triggered playback.

Technique 1 — The Draw-On Stroke Effect

The most iconic SVG path animation is the line drawing effect — where a path appears to draw itself onto the screen. It works by exploiting two stroke properties:

  • stroke-dasharray — sets the length of dash segments. Setting it equal to the total path length creates one solid dash that covers the entire path.
  • stroke-dashoffset — shifts the dash pattern. At full path length, the entire stroke is shifted off-screen. Animating to 0 reveals it.
/* Step 1: Get path length (run once in browser console) */
/* document.querySelector('path').getTotalLength() → e.g. 520 */

path {
  stroke-dasharray: 520;
  stroke-dashoffset: 520;
  animation: drawPath 1.8s ease-out forwards;
}

@keyframes drawPath {
  to { stroke-dashoffset: 0; }
}

Tip: Use animation-fill-mode: forwards so the path stays visible after the animation completes. Without it, the stroke resets to invisible.

Technique 2 — SMIL Path Animation

SMIL (Synchronized Multimedia Integration Language) lets you embed animation directly inside SVG markup. This means the animation works even in a plain .svg file opened in a browser — no CSS, no JavaScript needed.

<svg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">
  <path
    d="M10 100 Q100 10 190 100"
    fill="none"
    stroke="#6366f1"
    stroke-width="3"
    stroke-dasharray="240"
    stroke-dashoffset="240"
  >
    <!-- SMIL animate: stroke-dashoffset 240 → 0 over 2s -->
    <animate
      attributeName="stroke-dashoffset"
      from="240"
      to="0"
      dur="2s"
      fill="freeze"
    />
  </path>
</svg>

The fill="freeze" attribute on <animate> is the SMIL equivalent of CSS animation-fill-mode: forwards — it holds the final value after playback.

Technique 3 — Animating Stroke Width and Color

Beyond the draw-on effect, you can animate any stroke property with CSS keyframes. Common patterns include pulsing stroke width and cycling stroke color for attention-grabbing highlights:

/* Pulsing stroke */
@keyframes strokePulse {
  0%, 100% { stroke-width: 2; stroke-opacity: 1; }
  50%       { stroke-width: 5; stroke-opacity: 0.4; }
}

/* Color cycling */
@keyframes strokeColor {
  0%   { stroke: #6366f1; }
  50%  { stroke: #ec4899; }
  100% { stroke: #6366f1; }
}

path.highlight {
  animation:
    strokePulse 2s ease-in-out infinite,
    strokeColor  4s linear infinite;
}

Technique 4 — Path Morphing (Shape Tween)

Path morphing animates the d attribute itself — smoothly transitioning one shape into another. SMIL supports this natively via <animate attributeName="d">, but with a strict requirement: both paths must have the same number of commands and command types.

<path d="M50 100 C50 50 150 50 150 100" fill="#6366f1">
  <animate
    attributeName="d"
    values="
      M50 100 C50 50 150 50 150 100;
      M50 150 C50 50 150 150 150 50;
      M50 100 C50 50 150 50 150 100
    "
    dur="3s"
    repeatCount="indefinite"
    calcMode="spline"
    keySplines="0.4 0 0.2 1; 0.4 0 0.2 1"
    keyTimes="0;0.5;1"
  />
</path>

Note: CSS does not natively support morphing the d attribute (except in very recent Chrome with path() functions). For cross-browser path morphing, SMIL or GSAP MorphSVG is the reliable choice.

Technique 5 — Motion Path (Moving Along a Path)

CSS offset-path (formerly motion-path) lets any element travel along an SVG path. This is great for animating icons, particles, or dots along a defined route:

.dot {
  offset-path: path("M10 80 C40 10 65 10 95 80 S150 150 180 80");
  offset-rotate: auto;
  animation: moveAlongPath 3s linear infinite;
}

@keyframes moveAlongPath {
  0%   { offset-distance: 0%; }
  100% { offset-distance: 100%; }
}

offset-rotate: auto automatically rotates the element to face the direction of travel — perfect for arrows or vehicles.

Staggered Multi-Path Animation

For logos or illustrations with multiple paths, staggering the draw-on timing creates an elegant sequential effect. Use CSS custom properties and animation-delay:

/* Each path sets its own length via a custom property */
path:nth-child(1) { --len: 180; animation-delay: 0s; }
path:nth-child(2) { --len: 240; animation-delay: 0.3s; }
path:nth-child(3) { --len: 160; animation-delay: 0.6s; }

path {
  stroke-dasharray: var(--len);
  stroke-dashoffset: var(--len);
  animation: drawPath 1.2s ease-out forwards;
}

@keyframes drawPath {
  to { stroke-dashoffset: 0; }
}

Generate SVG Path Animations Visually

Manually calculating getTotalLength() and writing keyframe code for every path is tedious. CSSVG handles this automatically — draw paths with the pen tool, set keyframes on the timeline, and export clean CSS or SMIL with one click. The draw-on animation toggle is built in.

Try It Free

Create SVG path animations visually. Export CSS keyframes, SMIL SVG, or a React component — zero subscription, zero runtime.

Open the Editor — it's free

Performance Notes

  • Prefer stroke animation over fill animation: Stroke-dashoffset is GPU-composited in most browsers. Animating fill triggers repaint.
  • Keep path complexity low for morphing: Complex paths with many nodes morph slowly. Simplify paths to under 20 nodes where possible.
  • Use will-change: transform on motion paths: Hints the browser to promote the element to its own compositor layer before the animation starts.
  • Respect prefers-reduced-motion: Wrap draw-on animations in @media (prefers-reduced-motion: no-preference) — line-drawing can be distracting for motion-sensitive users.