GSAP stopped charging for its SVG plugins on April 30, 2025, when Webflow made it free for all users, including the former Club plugins for path drawing and morphing (Webflow, 2025). Any comparison that still lists those plugins as paid is out of date.
With price off the table, the choice mostly comes down to bundle size and scroll support, plus whether a library can do the technique you need at all. GSAP, Anime.js, Vivus, SVG.js and Motion cover the practical range, from single-purpose path drawing to full timelines.
Front-end developers usually reach for one where CSS and SMIL give out. Sequencing many paths is the common trigger. Morphing between shapes and tying motion to scroll come up too.
What do SVG animation libraries do that plain SVG cannot?
Because SVG graphics are markup, every path, circle and group is a DOM node that a script can reach. A library writes new attribute values to those nodes on every frame, usually through requestAnimationFrame, and handles the timing and easing so you don’t have to.
The real gain is one consistent JavaScript API for strokes, paths and transforms, which plain SVG doesn’t give you.
Path drawing is the technique everybody knows. It animates stroke-dashoffset against stroke-dasharray so a line looks hand-drawn. Path morphing interpolates the d attribute from one shape to another, and motion along a path moves an element along the coordinates and angle of a path. Staggering offsets start times across many elements, while timelines chain steps together, so changing one duration shifts everything after it.
Lottie players work differently. They play back a JSON file exported from After Effects, so your own code isn’t writing any attributes.
When are CSS, SMIL and the Web Animations API enough?
One or two simple icons rarely need a library. A looping spinner or a hover transform works natively, and so does a single stroke draw, with no script added.
Plain CSS covers transforms, opacity, fill and stroke-dashoffset. For one icon, animating SVG with CSS costs nothing in page weight.
The motion sits in CSS keyframes that loop without any script. Sequencing is where it falls over: ten paths drawn in order need ten hand-calculated delays, and shapes with different point counts do not morph.
SMIL uses declarative animate, animateTransform and animateMotion elements that sit inside the SVG. A 2015 Chromium proposal on the blink-dev list sought to deprecate SMIL in favor of CSS and Web Animations, but Chrome suspended it in 2016, and SMIL still works in current browsers. It stays declarative, so it suits self-running loaders and not motion tied to user input.
The Web Animations API is the other native route. Element.animate() has been Baseline widely available since March 2020, according to MDN. It drives CSS properties from JavaScript with keyframes and playback control, but sequencing across elements is still code you write.
My rule is simple. Stay native for one self-contained animation. Once elements need to run in order or shapes need to morph, bring in a library. Same if motion has to follow scroll or clicks.
Which SVG animation library should you use?
Nothing wins every job here. GSAP covers the widest range of SVG work. Anime.js is lighter and still does most of it, and Vivus only draws lines.
| Library | Best job | SVG tooling | Footprint |
|---|---|---|---|
| GSAP | Complex timelines, scroll stories | DrawSVGPlugin, MorphSVGPlugin, MotionPathPlugin | Core plus plugins |
| Anime.js | General animation with SVG helpers | morphTo, createDrawable, createMotionPath | Modular imports in v4 |
| Vivus | Line drawing on existing SVGs | Path drawing only | No dependencies |
| SVG.js | Building and animating SVG from code | Size, position, transforms, color | No dependencies |
| Motion | Small bundles, React and vanilla | pathLength drawing in the hybrid build | Mini or hybrid build |
A few numbers help here. GSAP became free for all users, former Club plugins included, on April 30, 2025 (Webflow announcement). Its core is about 27kb gzipped in the current npm build (gsap 3.15.0, per depscope), and plugins add to that. Motion’s mini build is 2.3kb and the hybrid build about 18kb (Motion documentation). Anime.js v4 has 3 SVG helpers, morphTo, createDrawable and createMotionPath (Anime.js documentation).
Bundle size depends on what you import, so measure your own build before committing.
GSAP
The price argument against GSAP is gone. What’s left is size and license wording.
One timeline chains path drawing with morphing and motion-path steps, and it brings labels, scrubbing and callbacks along. DrawSVGPlugin and MorphSVGPlugin ship in the same npm package, and so does ScrollTrigger. You’d rarely need a second library for any SVG technique.
The downsides are real, though. It’s the heaviest entry in the table once plugins load. The license is a custom “no charge” one and not MIT, so read the wording before bundling it into a product that lets customers build animations without code.
Anime.js
Anime.js v4 fits when GSAP feels like too much and Vivus too little. Its SVG module covers morphing and drawing, plus motion paths, without a plugin step.
Timelines, staggering and the SVG helpers sit in one modular package, and v4 lets you import only the parts a page uses. One catch if you’re following older tutorials: v3 code built on anime.setDashoffset doesn’t match v4, which draws lines with createDrawable.
Vivus
Vivus draws lines. That’s the whole product.
It has no dependencies, and one constructor call starts the animation. There are several draw styles, including sync, oneByOne and delayed. What you don’t get is morphing, timelines or motion paths.
The README also warns that a custom pathTimingFunction is called on every frame for every path, so keep it simple on SVGs with many paths.
SVG.js
SVG.js builds and manipulates SVG from code, and its animate() call tweens size, position, transforms and color. The npm package, whose latest release is 3.2.8, describes it as a lightweight library for manipulating and animating SVG.
It’s MIT licensed with no dependencies. Runners and timelines are built into the core, so you can sequence animations and run several elements on one shared timeline. One API covers every shape type, which suits generating SVG as much as animating it.
Scroll scrubbing and stroke-based path drawing aren’t built in, so you write that code yourself or add a plugin.
Motion
Motion is the one entry whose headline size comes with a catch. The mini build animates HTML and SVG styles through native browser APIs, but line drawing needs the hybrid build.
The hybrid animate() handles pathLength drawing, sequences and staggering. Motion along a path comes from the arc() helper or CSS offset-path. The mini build keeps simple animations tiny, but the 2.3kb figure no longer applies once you animate SVG paths. Bundle analyzers also tend to report the whole package, which inflates the number.
Decision rules by job
- For drawing an existing logo or icon, use Vivus, or createDrawable in Anime.js if the page already loads it.
- A multi-step sequence with scroll scrubbing belongs to GSAP with ScrollTrigger.
- Morphing between shapes on a light bundle is a job for Anime.js morphTo.
- In a React app, Motion.
- For charts driven by data, D3.js transitions make more sense because the library already binds data to SVG nodes.
- mo.js, built as a motion graphics library, suits burst and shape effects.
Are Snap.svg, Velocity.js and other older libraries still worth using?
Not for new projects. Roundups still list them without dates, but both have gone quiet.
As of October 2026, npm lists 0.5.1 as the latest Snap.svg release, published in February 2017. Adobe’s Web Platform Team helped build it, which is why it still shows up in older tutorials.
Velocity.js is in a similar spot. The README still installs version 2 under the beta tag and points to 2.0.6 on the CDN.
SVG.js or GSAP take over Snap.svg’s role of manipulating and animating SVG. Velocity’s jQuery-style animate calls map to Anime.js or Motion.
An older library earns its place only in a codebase that already ships it and needs no new effects. Check the repository’s last release before copying code from any roundup.
When should you use Lottie or an animation editor instead of code?
Use Lottie or an editor when a designer owns the motion and the animation needs no live data. If it reacts to scroll, clicks or application state, use a code library.
The Lottie pipeline starts in Adobe After Effects, where animators build the motion. The Bodymovin extension exports it as JSON, and Airbnb’s lottie-web player renders it with a renderer setting of svg, canvas or html.
Lottie suits micro-interactions such as an animated checkmark or a loading state, where a designer wants to polish timing in After Effects instead of in code.
File weight favors it. Most Lottie animations average under 10KB, with dotLottie averaging 3 to 4KB, according to LottieFiles (October 2024).
LottieFiles quotes dotLottie savings as up to 80% in its documentation and up to 10x on its platform page. Both are vendor figures, so test your own file.
The player is a runtime you still load, and plain Lottie JSON does not carry interactivity on its own (LottieFiles). The lottie-web title and description renderer settings add SVG title and desc elements, a start toward accessible SVG files that still needs text you write yourself.
SVGator, a no-code SVG editor, exports animated SVG in two modes, according to its help center.
The CSS-only mode needs no player and keeps files smaller. The trade is fewer animators and less interactivity, with no click or scroll-into-view triggers. Browser support for morphing and motion paths is uneven, and Safari lacks CSS morphing.
The JavaScript mode adds click and scroll-into-view triggers, morphing and path animation. It carries a lightweight player that can be embedded in the file or hosted externally.
| Workflow | Pros | Cons |
|---|---|---|
| Code library | Full runtime control, scroll and state | Needs a developer, script weight |
| Lottie | After Effects pipeline, small files | Player runtime, no interactivity in plain JSON |
| Editor export | No code, CSS mode needs no runtime | CSS mode is limited, JavaScript mode ships a player |
Pick by who owns the animation. Developers should write code, teams already working in After Effects should use Lottie, and designers who want neither can use an editor.
How do you animate an SVG path with a library?
The steps are the same in GSAP, Anime.js and Vivus. Inline the SVG, make sure each shape has a stroke, tween the stroke-dashoffset through one library call, then chain the calls on a timeline.
Libraries need a DOM they can reach, which is why SVG in HTML markup works where an img tag does not.
- Inline the SVG or load it through an object tag. The W3C SVG 2 specification processes SVG used as an image in secure animated mode, which plays CSS and SMIL but blocks scripts.
- Check the strokes. DrawSVGPlugin works through stroke-dashoffset and stroke-dasharray and never touches fill, so fill-only shapes need a stroke first.
- Call the library on the path, using one of the calls in the table below.
- Stagger or chain the paths on a timeline so each one starts when the previous one finishes.
| Library | Call | Draw behavior |
|---|---|---|
| GSAP | gsap.from(“.draw-me”, { duration: 1, drawSVG: 0 }) | Reveals the stroke, accepts ranges such as 20% 80% |
| Anime.js | animate(svg.createDrawable(“path”), { draw: “0 1” }) | Draws each path from start to end |
| Vivus | new Vivus(“my-svg”, { type: “oneByOne”, duration: 200 }) | Draws each path in turn |
Clean the file before you target paths. SVG optimization strips redundant groups and generated ids, so keep the ids and classes your selectors rely on.
If nothing draws, the shape probably has no stroke, or GSAP never ran gsap.registerPlugin(DrawSVGPlugin). If the line length drifts on resize, look at vector-effect non-scaling-stroke, which changes the stroke length when the SVG resizes and breaks hand-written dashoffset code. GreenSock staff say DrawSVGPlugin adjusts for it automatically.
How do you trigger SVG animation on scroll?
Bind the animation’s progress to scroll position for scrubbed effects, or fire it once when the element enters the viewport. Which of the two you need decides the library.
In GSAP, ScrollTrigger is a separate plugin, not part of the core. It offers scrub, pin, start and end positions and visual markers, and it attaches to a timeline.
Anime.js takes a different route. Pass onScroll() to the autoplay parameter and it synchronizes animations, timelines and timers with scroll, using several sync modes (Anime.js documentation).
Motion’s scroll() is its own 5.1kb function. It hands supported animations to the browser’s ScrollTimeline for hardware acceleration and falls back to the main thread otherwise (Motion documentation).
The usual pattern is a pinned timeline where DrawSVGPlugin draws the path and ScrollTrigger scrubs it.
Native scroll-driven CSS animations use animation-timeline: scroll() and need no script. MDN currently lists animation-timeline as limited availability, not Baseline, so ship a fallback.
ScrollTrigger does not constantly recalculate start and end values. Call ScrollTrigger.refresh() after layout changes, per the GSAP documentation.
Scrubbing stacked SVG layers at different rates produces a parallax scrolling effect.
Where do SVG animation libraries break down?
They break down at transform origins, heavy node counts, autoplay loops and ignored motion preferences. Each has a native fix that costs little.
| Condition | Symptom | Fix |
|---|---|---|
| Rotating or scaling a shape | Shape swings around the canvas origin | transform-box: fill-box with a centered origin |
| Many animated nodes or filters | Frame rate drops | Animate groups, profile first |
| Autoplay loop over five seconds | Fails WCAG 2.2.2 | Add a pause control |
| Reduced-motion setting ignored | Full motion plays anyway | Check prefers-reduced-motion |
Transform origin surprises
MDN lists the transform-box property as Baseline widely available, with support across browsers since January 2020.
SVG elements default to a transform-origin of 0 0, the origin of the viewBox, so a rotation swings around the canvas corner instead of the shape. Setting transform-box to fill-box moves the origin to the shape’s bounding box.
Browser support is no longer the obstacle, so cross-browser compatibility problems here usually come from a missing declaration.
Performance ceilings
Every frame, a library writes attributes and the browser repaints what changed.
The documentation for these libraries gives no hard limit on animated nodes, so profile your own page. Animate a group instead of fifty children, and prefer transforms and opacity to per-frame filter changes. Then record a trace in the browser’s Performance panel and read the frame rate.
Reduced motion and pause controls
The prefers-reduced-motion media feature has been available across browsers since January 2020, according to MDN. It signals that the user wants motion removed, reduced or replaced.
W3C’s WCAG 2.2.2 requires a pause, stop or hide mechanism for motion that starts automatically, lasts more than five seconds, and runs alongside other content.
Treat both as part of web accessibility work for every animated hero or loader.
When the preference is set, skip the timeline and render the end state, or swap a long draw for a short fade. For any loop that runs past five seconds, a visible pause button covers the requirement.
SVG Animation Libraries FAQ
How do you clean up SVG animations in React components?
Use GSAP’s useGSAP hook from @gsap/react. It replaces useEffect or useLayoutEffect and reverts every animation and ScrollTrigger created inside it when the component unmounts, according to the GSAP documentation.
Run library code on the client only, never during server rendering.
Does animating an SVG hurt Core Web Vitals?
Rarely. Cumulative Layout Shift only counts elements that change their start position (web.dev), so path drawing, which moves nothing, does not register.
Animating top or left can shift layout. A transform cannot.
Can SVG animation libraries animate filters and masks?
Yes. Filter primitives expose ordinary attributes, and MDN lists the feTurbulence baseFrequency attribute as animatable, so any library that tweens SVG attributes can drive it. Masks work the same way through the attributes of the shapes inside them.
Expect a higher repaint cost than with transforms, because the browser re-renders the filtered area every frame.
How do you prepare a Figma export for animation?
Name your layers, then switch on Include “id” attribute in the SVG export settings. Figma writes layer names as element ids, which gives your selectors something to target.
Turn on Simplify stroke as well. Inside and outside strokes then export as stroke attributes instead of masks, which path drawing needs, at the price of an approximation of the original look.
What Does Switching SVG Animation Libraries Cost?
Path drawing is cheap to move between libraries. Scroll is not. The SVG file survives the move, but the sequencing and scroll code does not.
Path drawing ports because GSAP’s DrawSVGPlugin works through stroke-dashoffset and stroke-dasharray, standard stroke properties any replacement can target. Scroll does not port: ScrollTrigger, Anime.js onScroll() and Motion scroll() are three separate APIs with no shared syntax.
That asymmetry sets the order of work. Label your layers, keep the SVG file clean and wrap the library calls in one module. Add scroll behavior last.
The wrapper is the trade-off. It adds a layer to maintain and hides library-specific features, which slows a quick prototype.
Skip it on a single page with one animation, where a rewrite stays small.
- What is Backend in Web Development? - September 13, 2026
- What is Frontend Development? - September 11, 2026
- How to Make a Button in Figma: Design Best Practices - September 10, 2026


