Skip to content

Choosing a Format

As the Introduction covered, the editor saves an animation in one of two formats: JSON, which a player library renders, or pre-rendered SVG, which a browser plays on its own. This page is about picking between them — and, for pre-rendered SVG, between its three flavours.

Both JSON and animated SVG are the same document in a different shape. You can switch at any time — File → Save as JSON / Save as SVG — so the choice is never final.

FormatFileWhat is insideNeeds a library?
JSON (“Pixodesk JSON”).jsonthe SVG tree + animation data + editor metadatayes — a player renders it
Pre-rendered SVG + CSS animation.svgordinary SVG + a <style> with @keyframes; starts on load, or on hover through CSS :hoverno
Pre-rendered SVG + CSS animation + JS triggers.svgthe above + a few lines of inline script — no library — that start/stop it on hover, click or scroll into viewno (the snippet is inline)
Pre-rendered SVG + JS animation.svgordinary SVG + the web player embedded in a <script> (25–38 KB)no (the player is inline)

The editor can also export Lottie (.json / .lottie), video, GIF and image snapshots — see Save, File Format.

JSON fits code: React, Vue, React Native, or vanilla JavaScript that needs runtime control. A pre-rendered SVG fits a file you drop into a CMS or static site with minimal setup — and that you need once per page (read more).

SituationPick
React / Vue / Next.js / Nuxt appJSON with the framework component — SSR-safe, full runtime control, every animation type. Or a CSS-flavour SVG imported like an icon (SVGR / vite-svg-loader) when you only need it to play, not to be controlled
Vanilla JavaScript page, you want play/pause from codeJSON + the web player, @pixodesk/svg-animator-web
Static site generator or CMS (Astro, Jekyll, WordPress, Shopify, Webflow)any pre-rendered SVG — the platform inlines the file; even the flavours with a <script> just work when inlined
Loader / icon / decorative loop, no interactionSVG + CSS animation — smallest, zero JavaScript
Start on hover without writing codeSVG + CSS animation — the export uses CSS :hover, no script at all
Start on click or scroll into view without writing codeSVG + CSS + JS triggers — a few inline lines (added by the editor app), no library
Content must be visible before any JavaScript runs, but the animation uses path morphing or another CSS-unsupported featureSVG + JS animation — the SVG is in the page from the first paint; the embedded player (25–38 KB) takes over and drives every animation type
Several copies of the same animation on one pageJSON — each instance gets fresh element ids; inlined SVGs can collide on ids
FormatAdvantagesLimitations
JSON• Every animation type on every browser
• full runtime control (play, pause, jump to any point, reverse, change speed)
• clean per-instance rendering, no id conflicts
• SSR-safe
You install a player package and add a few lines of code — the .json file does nothing on its own, unlike a pre-rendered SVG you can simply paste in
SVG + CSS• No library, smallest file
• no <script>, so it works inline and through SVGR
• starts on load or on hover (:hover)
• drop-in icon replacement
• Only what CSS @keyframes can express — see What each engine can animate below
• path morphing only between same-structure paths, and not in older browsers
• no runtime API — playback is controlled with CSS classes
id conflicts if inlined twice (one copy per page)
SVG + CSS + JS triggersSame as above plus click and scroll-into-view triggers, out actions and reset-on-finish — a few inline lines, no library• Same CSS limits
• no precise control (no jumping to a time, no reverse, no speed change)
• the <script> prevents SVGR use
id conflicts if inlined twice (one copy per page)
SVG + JS animation• Every animation type
• full runtime control
• self-contained
• Embeds the player (25–38 KB)
• the <script> prevents SVGR use
• possible id conflicts if inlined twice

Three things can drive an animation. The SVG + CSS animation flavour is driven by CSS @keyframes alone. JSON and the SVG + JS animation flavour are driven by the player, which has two engines: the Web Animations API (native, very smooth) and a frame loop (requestAnimationFrame, universal). With the default mode: 'auto' the player picks WAAPI and falls back to frames automatically whenever the document animates something WAAPI cannot express — so with a player every row below just works. The columns tell you which mechanism drives it and, more importantly, what the CSS flavour cannot do.

Animation typeSVG + CSS animation
CSS @keyframes
JSON · SVG + JS animation
Web Animations API engine
JSON · SVG + JS animation
Frame loop engine
Numeric attributes (opacity, stroke-width…)
Position (x, y, cx, cy, r, rx, ry)✅ ¹✅ ¹
Size (width, height)✅ ¹✅ ¹
Transform (translate, rotate, scale, skew)
Colours (fill, stroke)
Path morphing (d)⚠️ recent browsers ²
Stroke dash
Gradient stops⚠️ colour only ³
Gradient geometry
Filters (blur, brightness…)
Clip-path / mask morphing
Text on a path (startOffset)❌ ⁴
Performance⚡ excellent⚡ excellentgood
Browser supportuniversalmodern browsersuniversal

¹ Geometry as CSS properties works in Chromium and WebKit; Firefox does not implement it — use JSON (frames fallback) when cross-browser geometry animation matters. ² CSS d: path() needs identical path command structure across keyframes, and older browsers do not support it at all (Safari added it only recently). When it matters, use JSON — the frame loop morphs paths everywhere. ³ Per-stop stop-color animates via CSS; stop offset and gradient geometry cannot be expressed in CSS at all. ⁴ The static text-on-path layout renders everywhere; only animating startOffset / textLength is impossible in CSS.

The editor warns you at every step. While you work, an attribute the chosen SVG flavour cannot animate is flagged on its timeline row and in the file-type picker, and the toolbar’s App warnings button lists them all with a one-click fix (switch to SVG + JS (Auto)). When you save or export, the same list is shown once more as a notice — “Some animations are not supported in this export format” — together with any feature the pre-rendered file may not reproduce exactly. Nothing is silently dropped.

EngineAdvantagesLimitations
CSS @keyframes• No JavaScript at all
• the browser plays it by itself, so it stays smooth even while the page is busy
• nothing to load
• can start on mouse over, using plain CSS
• The smallest feature set — see the ❌ cells in the What each engine can animate table above
• geometry properties do not animate in Firefox
• no runtime API — playback is controlled with CSS classes
Web Animations API• Played by the browser itself, so it stays smooth even while the page is busy
• full runtime control
• no JavaScript runs while it plays
• Cannot express structural changes: path morphing, gradient geometry, filters, masks, text on a path
• modern browsers only
Frame loop• Every animation type, in every browser
• full runtime control
• the only engine for path morphing in older Safari
• JavaScript updates the SVG on every frame, so a page that is busy with other work can make it stutter
• runs uncapped unless you set frameRate
• still fast in practice, but the Web Animations API stays smoother under load

In JSON you rarely choose: mode: 'auto' uses WAAPI and switches to the frame loop only for what WAAPI cannot do. The choice that matters is the pre-rendered one — SVG + CSS locks you to the first row.

Any time: open the document and File → Save as JSON or Save as SVG. Keep the JSON as your master copy — it holds the animation exactly as you authored it, with every effect still an effect. The pre-rendered SVG is the finished result, everything already expanded into plain SVG: the file you put on a page. Both re-open in the editor.

Every route from the editor’s exports to a running animation (<object>/<iframe> embedding works but is not recommended):

%%{init: {'theme':'base', 'themeVariables': {'edgeLabelBackground':'white'}, 'flowchart':{'nodeSpacing': 100, 'rankSpacing': 80, 'curve': 'basis'}}}%%
graph TD
    App(["Pixodesk SVG Animator"])
    
    JSON["JSON file<br/>elements + animation data"]
    CSSkeyframes["Pre-rendered SVG<br/>+ CSS Keyframes<br/>(lightweight)"]
    CSSjs["Pre-rendered SVG<br/>+ CSS Keyframes<br/>+ JS Event Triggers"]
    JSanim["Pre-rendered SVG<br/>+ JS Animation<br/>(@pixodesk/svg-animator-web)"]
    
    ReactVue["React / Vue<br/>Components"]
    VanillaJS["Vanilla JS<br/>DOM Manipulation"]
    Embed["Embed/Inline<br/>into Static HTML"]

    App ---> JSON
    App ---> CSSkeyframes
    App ---> CSSjs
    App ---> JSanim

    JSON --->|"@pixodesk/svg-animator-react<br/>@pixodesk/svg-animator-vue"| ReactVue
    JSON --->|"@pixodesk/svg-animator-web"| VanillaJS

    CSSkeyframes --->|SVGR / vite-svg-loader| ReactVue
    CSSkeyframes --->|Direct inline| Embed

    CSSjs --->|"&lt;object&gt; / &lt;iframe&gt;<br/>(not recommended)"| VanillaJS
    CSSjs --->|Direct inline| Embed

    JSanim --->|"&lt;object&gt; / &lt;iframe&gt;<br/>(not recommended)"| VanillaJS
    JSanim --->|Direct inline| Embed
    
    style App fill:#3178c6,color:#fff
    style JSON fill:#4ecdc4,color:#fff
    style CSSkeyframes fill:#ffaa6b,color:#fff
    style CSSjs fill:#ff6b6b,color:#fff
    style JSanim fill:#ff6b6b,color:#fff
    style ReactVue fill:#61dafb,color:#000
    style VanillaJS fill:#f0db4f,color:#000
    style Embed fill:#95e1d3,color:#000