A lightweight animation library for Svelte 5 that provides smooth, hardware-accelerated animations. Features include spring physics, custom easing, and fluid transitions. Built on top of the motion library, it offers a simple API for creating complex anim
npm install @humanspeak/svelte-motion










Motion vibes, Svelte runes. This brings Motion’s declarative animation goodness to Svelte with motion. components, interaction props, and composable config. If you spot a cool React example, drop it in an issue—we’ll port it. 😍
Requests welcome: Have a feature/prop/example you want? Please open an issue (ideally include a working Motion/React snippet or example link) and we’ll prioritize it.
All standard HTML and SVG elements are supported as motion components (e.g., motion.div, motion.button, motion.svg, motion.circle). The full set is generated from canonical lists using html-tags, html-void-elements, and svg-tags, and exported from src/lib/html/.
- HTML components respect void elements for documentation and generation purposes.
- SVG components are treated as non-void.
- Dashed tag names are exported as PascalCase components (e.g., color-profile → ColorProfile).
This package includes support for MotionConfig, which allows you to set default motion settings for all child components. See the React - Motion Config for more details.
``svelte`
Svelte Motion supports minimal layout animations via FLIP using the layout prop:
`svelte`
- layout: smoothly animates translation and scale between layout changes (size and position).
- layout="position": only animates translation (no scale).
Animate elements as they leave the DOM using AnimatePresence. This mirrors Motion’s React API and docs for exit animations (reference).
`svelte
{#if show}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0.9 }}
transition={{ duration: 0.5 }}
class="size-24 rounded-md bg-cyan-400"
/>
{/if}
`
- The exit animation is driven by exit and will play when the element unmounts.exit.transition
- Transition precedence (merged before running exit):
- (highest precedence)transition
- component (merged with MotionConfig){ duration: 0.35 }
- fallback default
#### Current Limitations
Some Motion features are not yet implemented:
- reducedMotion settingsfeatures
- configurationtransformPagePoint
- Performance optimizations like layoutId
- Advanced transition controls
- Shared layout / (planned)
This package carefully selects its dependencies to provide a robust and maintainable solution:
- motion
- High-performance animation library for the web
- Provides smooth, hardware-accelerated animations
- Supports spring physics and custom easing
- Used for creating fluid motion and transitions
| Motion | Demo / Route | Live Demo |
| -------------------------------------------------------------------------------------------------------- | ---------------------------------------- | ---------------------------------------------------------------------------------------------- |
| React - Enter Animation | /tests/motion/enter-animation | View Example |/tests/motion/html-content
| HTML Content (0→100 counter) | | View Example |/tests/motion/aspect-ratio
| Aspect Ratio | | View Example |/tests/motion/hover-and-tap
| Hover + Tap (whileHover + whileTap) | | View Example |/tests/motion/while-focus
| Focus (whileFocus) | | View Example |/tests/motion/rotate
| Rotate | | View Example |/tests/random/shiny-button
| Random - Shiny Button by @verse\_ | | View Example |/tests/random/fancy-like-button
| Fancy Like Button | | View Example |/tests/motion/keyframes
| Keyframes (square → circle → square; scale 1→2→1) | | View Example |/tests/random/animated-border-gradient
| Animated Border Gradient (conic-gradient rotate) | | View Example |/tests/animate-presence/basic
| Exit Animation | | View Example |
Svelte Motion now supports hover interactions via the whileHover prop, similar to React Motion/Framer Motion.
`svelte`
- whileHover accepts a keyframes object. It also supports a nested transition to override the global transition for hover only:
`svelte`
transition={{ duration: 0.25 }}
/>
- Baseline restoration: when the pointer leaves, changed values are restored to their pre-hover baseline. Baseline is computed from animate values if present, otherwise initial, otherwise sensible defaults (e.g., scale: 1, x/y: 0) or current computed style where applicable.(hover: hover)
- True-hover gating: hover behavior runs only on devices that support real hover and fine pointers (media queries and (pointer: fine)), avoiding sticky hover states on touch devices.
`svelte`
- Callbacks: onTapStart, onTap, onTapCancel are supported.whileTap
- Accessibility: Elements with are keyboard-accessible (Enter and Space).onTapStart
- Enter or Space down → fires and applies whileTap (Space prevents default scrolling)onTap
- Enter or Space up → fires onTapCancel
- Blur while key is held → fires MotionContainer
- sets tabindex="0" automatically when whileTap is present and no tabindex/tabIndex is provided.
`svelte`
- Animates when the element receives keyboard focus and restores baseline on blur.
- Callbacks: onFocusStart, onFocusEnd are supported.
- Perfect for keyboard navigation and accessibility enhancements.
`svelte`
/ ... /
}}
onAnimationComplete={(def) => {
/ ... /
}}
/>
Variants allow you to define named animation states that can be referenced throughout your component tree. They're perfect for creating reusable animations and orchestrating complex sequences.
Instead of defining animation objects inline, create a Variants object with named states:
`svelte
`
One of the most powerful features is automatic propagation through component trees. When a parent changes its animation state, all children with variants defined automatically inherit that state:
`svelte
`
How it works:
- Parent sets animate="visible"variants
- Children with automatically inherit "visible" stateanimate
- Each child resolves its own variant definition
- No need to pass props to children!
Create staggered animations with transition delays:
`svelte`
{#each items as item, i}
{item}
{/each}
See the Variants documentation for complete details and examples.
Motion components render their initial state during SSR. The container merges inline style with the first values from initial (or the first keyframes from animate when initial is empty) so the server HTML matches the starting appearance. On hydration, components promote to a ready state and animate without flicker.
`svelte`
animate={{ opacity: 1 }}
style="width: 100px; height: 50px"
/>
Notes:
- Transform properties like scale/rotate are composed into a single transform style during SSR.initial
- When is empty, the first keyframe from animate is used to seed SSR styles.initial
- can be false to not run on initial
- Returns a Svelte readable store that updates once per animation frame with elapsed milliseconds since creation.
- If you pass an id, calls with the same id return a shared timeline (kept in sync across components).0
- SSR-safe: Returns a static store when window is not available.
`svelte
} />`
- Runs a callback on every animation frame with the current timestamp.
- The callback receives a DOMHighResTimeStamp representing the time elapsed since the time origin.$effect
- Returns a cleanup function that stops the animation loop.
- Best used inside a to ensure proper cleanup when the component unmounts.window
- SSR-safe: Does nothing and returns a no-op cleanup function when is unavailable.
`svelte
- Reference: Motion useAnimationFrame docs motion.dev.
$3
useSpring creates a readable store that animates to its latest target with a spring. You can either control it directly with set/jump, or have it follow another readable (like a time-derived value).`svelte
filter: blur(${$blur}px)} />
`- Accepts number or unit string (e.g.,
"100vh") or a readable source.
- Returns a readable with { set, jump } methods when used in the browser; SSR-safe on the server.
- Reference: Motion useSpring docs motion.dev.$3
useTransform creates a derived readable. It supports:- Range mapping: map a numeric source across input/output ranges with optional
{ clamp, ease, mixer }.
- Function form: compute from one or more dependencies.Range mapping example:
`svelte
rotate: ${$rotate}deg} />
`Function form example:
`svelte
{$total}
`- Reference: Motion useTransform docs motion.dev.
Access the underlying element (bind:ref)
You can bind a ref to access the underlying DOM element rendered by a motion component:
`svelte
{#if el}
{/if}
``License
MIT © Humanspeak, Inc.
Credits
Made with ❤️ by Humanspeak