GuideMay 2026 · 9 min read

Inline SVG Animation: Complete Guide for Web Developers

Inline SVG unlocks the full power of SVG animation — CSS selectors, JavaScript control, hover states, and SMIL all work when the SVG is embedded directly in HTML. This guide shows you everything.

Inline SVG vs External SVG — Which Supports Animation?

There are four ways to embed SVG in HTML — and they differ significantly in what animation techniques are available:

MethodCSS AnimationJS ControlSMIL
Inline <svg>✅ Full✅ Full✅ Yes
<img src=".svg">❌ No❌ No✅ Yes
CSS background-image❌ No❌ No✅ Yes
<object> / <embed>⚠️ Limited⚠️ Limited✅ Yes

Inline SVG is the only embedding method that gives you the complete toolbox — CSS keyframes via external stylesheets, JavaScript DOM access, SMIL, and hover/focus states from the parent document.

How to Embed SVG Inline in HTML

Copy the SVG source code from your editor or exporter and paste it directly into your HTML. Remove the XML declaration and any xmlns:xlink attributes that modern browsers no longer need:

<!DOCTYPE html>
<html>
<body>

  <!-- Inline SVG — full CSS and JS access -->
  <svg
    viewBox="0 0 200 200"
    width="200"
    height="200"
    xmlns="http://www.w3.org/2000/svg"
    class="my-icon"
  >
    <circle cx="100" cy="100" r="50" fill="#6366f1" class="circle" />
    <path d="M60 100 L100 60 L140 100" fill="none" stroke="white" stroke-width="3" />
  </svg>

</body>
</html>

Animating Inline SVG with CSS

Once the SVG is inline, any CSS class, selector, or keyframe defined in your stylesheet applies directly to SVG elements. This is the biggest advantage of inline SVG — you get full CSS power with zero extra setup.

/* Rotate the circle continuously */
.circle {
  transform-box: fill-box;
  transform-origin: center;
  animation: spin 3s linear infinite;
}

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

/* Fade in the whole SVG on load */
.my-icon {
  animation: fadeUp 0.8s ease-out forwards;
}

@keyframes fadeUp {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: translateY(0); }
}

Always add transform-box: fill-box to SVG elements you rotate or scale. Without it, the transform origin defaults to the top-left of the SVG viewport, causing the element to orbit or scale from the wrong point.

Hover Animations on Inline SVG

Inline SVG supports CSS :hover both on the SVG element itself and on individual child elements. This enables interactive icon animations that are impossible with <img> tags:

/* Hover the SVG → animate a child path */
.icon-svg path {
  transition: stroke 0.2s ease, stroke-width 0.2s ease;
}

.icon-svg:hover path {
  stroke: #a5b4fc;
  stroke-width: 2.5;
}

/* Hover a specific child element directly */
.icon-svg circle {
  transition: r 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
}

.icon-svg circle:hover {
  r: 60; /* SVG presentation attribute — animatable via CSS */
}

Animating Inline SVG with JavaScript

Inline SVG elements are part of the DOM, so you can select and manipulate them with querySelector, set attributes directly, or use the Web Animations API:

// Web Animations API — programmatic keyframes on an SVG element
const circle = document.querySelector(".my-icon circle");

circle.animate(
  [
    { transform: "scale(1)",   opacity: 1 },
    { transform: "scale(1.3)", opacity: 0.7 },
    { transform: "scale(1)",   opacity: 1 },
  ],
  {
    duration: 1200,
    easing: "ease-in-out",
    iterations: Infinity,
  }
);

The Web Animations API (WAAPI) is well-supported in all modern browsers and gives you play/pause/reverse control via JavaScript — without loading a third-party library.

SMIL Inside Inline SVG

SMIL <animate> and <animateTransform> tags work inside inline SVG exactly as they do in standalone .svg files. This is useful for animations that must survive copy-paste into an email or CMS that strips CSS:

<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
  <circle cx="50" cy="50" r="20" fill="#6366f1">
    <!-- SMIL: pulse the radius -->
    <animate
      attributeName="r"
      values="20;30;20"
      dur="1.5s"
      repeatCount="indefinite"
      calcMode="spline"
      keySplines="0.4 0 0.2 1;0.4 0 0.2 1"
    />
    <!-- SMIL: fade opacity -->
    <animate
      attributeName="opacity"
      values="1;0.5;1"
      dur="1.5s"
      repeatCount="indefinite"
    />
  </circle>
</svg>

Performance Tips for Inline SVG Animation

  • Keep inline SVG small: Large inline SVG bloats HTML and delays First Contentful Paint. If the SVG is above the fold or decorative, lazy-load or defer it.
  • Use IDs for complex SVGs: Inline SVGs share a DOM with the page. Use unique IDs and class names — duplicate IDs cause rendering bugs.
  • Animate transform and opacity only: Both trigger GPU compositing. Animating fill or stroke triggers repaint on many browsers.
  • Add aria-hidden for decorative SVG: If the SVG is purely decorative, add aria-hidden="true" to remove it from the accessibility tree.

Using React Components with Inline SVG

In React, inline SVG is just JSX. Export your animation as a React component from CSSVG and drop it directly into your app — it receives props, responds to state, and integrates with Framer Motion or CSS modules:

// React inline SVG component (exported from CSSVG)
export function LogoAnimation({ size = 120 }: { size?: number }) {
  return (
    <svg
      width={size}
      height={size}
      viewBox="0 0 200 200"
      fill="none"
      xmlns="http://www.w3.org/2000/svg"
      aria-hidden="true"
    >
      <circle cx="100" cy="100" r="60" fill="#6366f1">
        <animate attributeName="r" values="60;72;60" dur="2s" repeatCount="indefinite" />
      </circle>
    </svg>
  );
}

Export Inline SVG from CSSVG

Build your animation visually on the CSSVG timeline, then export as a React JSX component with inline SMIL, a standalone SVG with SMIL, or a CSS keyframes bundle. All export formats produce inline-ready SVG.

Open the Editor — it's free