SVG Motion Studio — Online SVG Animator with Timeline, Lottie & ScrollTrigger Export
What's included
Features
About this tool
Animate SVG Logos, Icons, and Illustrations — Export CSS, GSAP, ScrollTrigger, Framer Motion, or Lottie
SVG Motion Studio is a browser-based SVG animation editor that takes you from a static vector file to production-ready animated code in minutes. Import any SVG by pasting markup, uploading a file, or pasting from clipboard — the studio instantly parses every group, path, shape, and text element into independently animatable layers on a shared multi-track timeline. No account, no install, nothing uploaded to a server.
The tool is built around the problem that most SVG animation workflows are either too manual (writing CSS keyframes by hand) or too locked in (proprietary platforms that own your output). SVG Motion Studio sits in the middle: a visual keyframe editor that generates clean, portable code you can drop directly into any web project.
Multi-track timeline shows every layer simultaneously as its own row. The cyan playhead spans all rows and stays locked in sync. Click any diamond keyframe to jump to that frame, drag it left or right to shift timing, or hold Shift while dragging to snap to 5% intervals. Adding a keyframe captures the interpolated state at the current playhead position so you never lose work in progress. Drag the ≡ handle on any layer row to reorder layers — order affects stagger timing and export output.
Keyframe properties go well beyond the basics. Every frame supports translate X and Y (position offset in pixels), scale, rotation in degrees, opacity, fill color (with inline color picker), blur in pixels, brightness, stroke-dasharray, and stroke-dashoffset. This makes effects like draw-on strokes, focus-pull exits, and glow pulses achievable without touching CSS. The two-column compact grid keeps all controls on screen at once.
Copy and paste keyframes across layers with Ctrl+C / Ctrl+V or the Keyframe Clipboard buttons in the inspector. Copy a layer's full animation, paste it to another layer, then tweak values — massively faster than rebuilding identical timing from scratch. Custom presets let you name and save any keyframe set to the My Presets panel. They sit alongside the 20 built-in presets and persist in localStorage between sessions.
Bezier curve editor opens with the ∿ button next to any easing dropdown — for global animation, per-layer overrides, or individual keyframe segments. Drag the two handles on the square grid: the handles always stay within the boundary while the curve stretches freely above and below for overshoot and spring effects. The easing dropdown auto-updates to the live cubic-bezier() value as you drag. Nine quick-apply presets (Bounce, Spring, Snappy, Smooth, and more) let you start from a named shape. Per-segment easing means the curve from frame 0 to frame 50 can be ease-in while frame 50 to frame 100 is bounce — which is how professional motion design actually works.
Stagger is a single slider in the Animation panel. Set it to 0.15 and every layer starts 0.15 seconds after the previous one, creating the cascading entrance effect used in landing page hero animations without manually setting a delay on each layer. Stagger is carried into all five export formats.
Export formats cover the full modern web stack. The CSS tab generates standard @keyframes with animation shorthand. The GSAP tab generates a gsap.timeline() with fromTo calls for each animation segment. The new ScrollTrigger tab wraps the same GSAP timeline in a scrollTrigger configuration block — toggle actions, start/end positions, and an optional scrub mode for scroll-linked animations. The Framer Motion tab generates motion.tag JSX with animate and transition props for React. The Lottie tab exports a standards-compliant Lottie JSON file at 60 fps, mapping translate, scale, rotation, and opacity keyframes to Lottie's transform properties — compatible with lottie-web, iOS, Android, and React Native.
Multi-project library lives in the header as a folder-icon project picker. Click it to see all your saved projects, switch between them instantly, create new ones with a custom name, rename any project inline, or delete one with a confirmation modal. Projects are stored in IndexedDB — more reliable than localStorage — so they survive cache clears and browser updates. Deleted projects are kept as tombstone records for 30 days so the deletion propagates correctly to every other device via Gist sync, then cleaned up automatically.
GitHub Gist sync keeps your entire project library safe across sessions and syncs it across devices without any account sign-up. Click the Gist button in the header, paste a GitHub Personal Access Token (gist scope), and the studio automatically pushes your full project library to a private Gist after every change. On your next visit — on any device — the latest library is pulled back and merged. The merge logic compares each project's updatedAt timestamp independently, so a rename on device A and an edit on device B both survive the sync without either one being overwritten. The token is shared across all FWD tools — one connection covers the whole suite.
Motion path lets a layer follow a custom SVG curve using CSS offset-path. Enable it in the Layer inspector, paste any SVG path d-value, and the element follows that arc over the animation duration while still compositing with whatever transform keyframes you have set. Undo and redo (Ctrl+Z / Ctrl+Y) tracks every change in a history stack. Export JSON / Import JSON preserves the complete project state for manual backup. Everything runs locally: no account, no cloud, no data leaving your browser.
Step by step
How to Use
- 1Import your SVGPaste SVG markup into the import field, click Upload to choose a .svg file, or press Paste to pull SVG directly from your clipboard. The studio parses the file, strips scripts and event handlers, and lists every group, path, shape, and text element as a named layer in the sidebar and timeline. Click the ≡ drag handle on any layer row to reorder layers — the order determines stagger timing in all exports.
- 2Select a layer and set keyframesClick any layer row in the timeline or click an element directly on the canvas preview to select it. Move the playhead to the moment you want to record, then click "+ Keyframe". Adjust X, Y, scale, rotation, opacity, fill color (inline color picker), blur, or brightness for that frame. Add as many keyframes as the animation needs — each layer's diamonds are visible on its own timeline row. To copy a layer's keyframes to another layer, press Ctrl+C on the source layer, select the target layer, and press Ctrl+V.
- 3Refine timing and easingDrag keyframe diamonds left or right on the timeline (hold Shift to snap to 5% intervals). Click the ∿ button next to any easing selector to open the bezier curve editor — drag the handles to sculpt the curve, or choose a quick preset like Bounce or Spring. Set per-layer delays and the stagger slider for cascading entrances. To save a keyframe set as a reusable preset, type a name in the My Presets input and click Save.
- 4Apply presets for common effectsUse the Motion Presets panel to apply pre-built animations with one click. Entrance presets add arrival keyframes; Emphasis presets create loops; Exit presets add departure keyframes; Draw presets animate stroke-dashoffset for path drawing. Each preset generates editable keyframes — tweak timing and values as needed. Saved custom presets appear in the My Presets section below the built-in ones.
- 5Preview with playback controlsPress Play (▶) to watch the full animation. Use the speed buttons (×0.5 / ×1 / ×2) to slow down or speed up for review. Toggle the preview background between dark, light, checkerboard, and custom color to see how the animation looks against its real usage context. Drag the time slider to scrub frame-by-frame.
- 6Export to CSS, GSAP, ScrollTrigger, Framer Motion, or LottieOpen the Export Code panel and choose a tab. CSS generates standard @keyframes for any stylesheet or embedded SVG. GSAP generates a gsap.timeline() with fromTo calls. ScrollTrigger wraps the GSAP timeline in a scroll-triggered configuration — change the trigger selector, start/end points, and optionally enable scrub mode for scroll-linked playback. Framer Motion generates motion.tag JSX for React. Lottie generates a 60-fps JSON file — click Download .json to save it for use in lottie-web, iOS, Android, or React Native. For session persistence, click the Gist button in the header to connect GitHub Gist sync.
- 7Keep your Gist private — never share the URLGitHub private Gists are not truly encrypted — they are unlisted links. Anyone who has your Gist URL or Gist ID can access your full project library without logging in. Never share your Gist URL, Gist ID, or Personal Access Token with anyone. For maximum privacy, skip Gist sync and use Export JSON to back up and transfer projects manually instead.
Real-world uses
Common Use Cases
Got questions?
Frequently Asked Questions
Every keyframe supports translate X and Y (position offset in pixels), scale, rotation in degrees, opacity (0–1), fill color, blur in pixels, brightness multiplier, stroke-dasharray, and stroke-dashoffset. You can also set a custom per-segment easing curve using the visual bezier editor, so the animation can ease differently between each pair of keyframes.
Yes. The Export Code panel has three tabs: CSS (standard @keyframes with animation shorthand), GSAP (a gsap.timeline() with fromTo calls for each layer segment, respecting per-layer delay and stagger), and Framer Motion (motion.tag JSX with animate and transition props for React projects). All three formats are derived from the same keyframe data so they stay in sync.
Click the ∿ button next to any easing selector to open the visual cubic-bezier editor. Drag the two control handles inside the square grid — the curve stretches freely beyond the grid for bounce and spring overshoot effects while the handles stay within reach. The dropdown auto-updates to show the live cubic-bezier() value. Nine quick-apply presets (Ease, Ease In, Bounce, Spring, Snappy, etc.) let you start from a named shape and fine-tune from there.
Stagger adds a delay offset between layers based on their order. Setting stagger to 0.15s makes layer 0 start at 0s, layer 1 at 0.15s, layer 2 at 0.30s, and so on. This creates the cascading entrance effect used in most modern motion design without manually setting a delay on every layer. Stagger is included in CSS, GSAP, and Framer Motion exports.
Yes. Each keyframe has Blur (px) and Brightness fields. Animating blur from 0 to 12 with the Blur Out preset creates a focus-out exit. Animating brightness from 1 to 1.8 and back creates a glow pulse. These values produce a CSS filter: blur() brightness() rule in the exported CSS and are included in GSAP and Framer Motion output as well.
Motion path lets a layer follow a custom SVG path using CSS offset-path. Enable it in the Layer inspector, paste any SVG path d-attribute value, and the element animates along that curve over the animation duration. Motion path composites with normal transform keyframes — the element can simultaneously follow a path and scale, rotate, or fade.
Yes. Every keyframe change — adding, removing, moving, or editing a frame — is tracked in a history stack. Press Ctrl+Z (or Cmd+Z on Mac) to undo and Ctrl+Y (or Ctrl+Shift+Z) to redo. The undo and redo buttons in the header also show which operations are available.
Click the folder icon in the header to open the project panel. Type a name and click Save to save the current SVG and all animation settings as a named project. Click Save as New to create a separate copy with a new name. All saved projects appear in a scrollable list — click any project name to switch to it instantly. Click the pencil icon to rename a project inline, or the x button to delete it (with a confirmation modal). Projects are stored in IndexedDB in your browser, so they persist across sessions without any sign-up. GitHub Gist sync pushes the full library — including all projects and deletion records — to a private Gist, making the same library available on every device.
Yes — in two ways. The multi-project library in the header lets you save unlimited named projects directly in the browser's IndexedDB. Click the folder icon in the header, type a project name, and click Save. Your projects persist across sessions and appear in the project picker for instant one-click switching. You can also click Export JSON to download a portable backup file and Import JSON to restore it. For cross-device persistence, connect GitHub Gist sync: paste a GitHub Personal Access Token with gist scope, click Save, and the studio automatically pushes your full project library to a private Gist. On any device, the latest library is fetched and merged on load.
GitHub Gist sync saves your entire multi-project library to a private GitHub Gist so your projects are accessible from any device. Click the GitHub icon in the header, paste a GitHub Personal Access Token (create one at github.com/settings/tokens with only the gist scope checked), and click Save. The studio finds or creates a private Gist named sms-motion-project.json and begins syncing automatically — pushing after every change (5-second debounce) and pulling on load. The merge logic compares each project's updatedAt timestamp independently, so edits and renames on different devices never overwrite each other. Deleted projects are stored as tombstone records so deletions also propagate correctly. The token is stored in your browser's localStorage and shared with all FWD tools — if you already set it up in another tool, SVG Motion Studio picks it up immediately.
Yes. The Export Code panel has a Lottie tab that generates a Lottie JSON file from your keyframe data. Lottie is the most widely supported SVG animation format — used by iOS, Android, React Native, and web apps via the lottie-web player. The export maps your translate (position), scale, rotation, and opacity keyframes to Lottie's transform properties at 60 fps. Click Download .json in the Lottie tab to save the file and load it in any Lottie player.
The ScrollTrigger tab generates GSAP animation code that plays as the user scrolls the page, using the GSAP ScrollTrigger plugin. The output includes gsap.registerPlugin(ScrollTrigger), a timeline with a scrollTrigger configuration block (trigger, start, end, toggleActions), and the same fromTo segment calls as the standard GSAP export. Change the trigger selector to your container element, adjust start and end positions, and optionally uncomment scrub: true to link the animation progress directly to the scroll position instead of playing it once.
Select the source layer, then click Copy Keyframes in the Keyframe Clipboard section of the inspector (or press Ctrl+C when not focused on an input field). The keyframes are stored in the clipboard panel. Then select the target layer and click Paste to Layer (or press Ctrl+V). The pasted keyframes replace the target layer's existing keyframes. This is useful for applying the same entrance animation to multiple layers before tweaking timing and values individually.
Drag the ≡ handle on the left edge of any layer row in the Layers panel to reorder it. Drag up or down — a highlight border shows where the layer will drop. Layer order affects stagger: layer 0 starts first, each subsequent layer is offset by the stagger value. Reordering is also reflected in the CSS, GSAP, Framer Motion, ScrollTrigger, and Lottie exports.
Set up keyframes on a layer exactly as you want them, then scroll to the My Presets section at the bottom of the sidebar. Type a name in the input field and click Save. Your preset appears in the list and can be applied to any layer with one click — just like the built-in motion presets. Custom presets are stored in IndexedDB and persist between sessions reliably. To delete a preset, click the x button next to it.
Use the Draw On preset from the Draw category. It sets stroke-dasharray to 1000 at frame 0 with stroke-dashoffset equal to 1000, then animates stroke-dashoffset to 0 by frame 100 — which draws the stroke progressively along the path. For best results, apply this to path or line elements that already have a stroke attribute. Adjust the dasharray value to match your actual path length for a perfect draw.
Yes. SVG parsing, layer extraction, keyframe calculation, preview rendering, and all export formats are processed entirely in your browser using the DOMParser and XMLSerializer APIs. No file content, layer data, or export output is ever sent to a server. It is safe to use with unreleased logos, NDA-protected brand assets, and client illustrations.
SVGs with named groups and elements work best — typically files exported from Figma, Illustrator, or Inkscape with layer names preserved as id attributes. The tool extracts every g, path, circle, rect, ellipse, line, polyline, polygon, and text element as a separate animatable layer. Simple illustrations with a handful of distinct sections (like a rocket with moon, stars, trail, body, and flame) are ideal. Very complex SVGs with hundreds of nested micro-paths still work but may produce a large layers list.
Yes — treat your Gist URL as a secret. GitHub "private" Gists are not encrypted — they are unlisted links. Anyone who has your Gist URL or Gist ID can access your full animation project library without needing a GitHub login. Never share your Gist URL, Gist ID, or Personal Access Token with anyone. For maximum privacy, skip Gist sync and use Export JSON to back up and transfer projects manually instead.