The unscoped svelte-motion package has not released since February 2024. It still has users, name recognition, and a familiar component model, but it predates Svelte 5’s runes-first ecosystem.
@humanspeak/svelte-motion is an actively maintained alternative built specifically for Svelte 5. It tracks the modern Motion API and includes AnimatePresence, gestures, drag, FLIP layout animation, shared-layout transitions, springs, scroll-linked values, and SSR-safe SvelteKit rendering.
This is a source migration rather than a package alias. The concepts transfer cleanly, but imports and component names need to change.
Replace the package
Remove the old dependency and install the scoped package:
pnpm remove svelte-motion
pnpm add @humanspeak/svelte-motionpnpm remove svelte-motion
pnpm add @humanspeak/svelte-motionThen replace generic Motion imports with either the familiar proxy API or tree-shakeable named components:
<script lang="ts">
import { motion } from '@humanspeak/svelte-motion'
</script>
<motion.div
initial={{ opacity: 0, y: 12 }}
animate={{ opacity: 1, y: 0 }}
transition={{ type: 'spring', stiffness: 320, damping: 24 }}
>
Migrated
</motion.div><script lang="ts">
import { motion } from '@humanspeak/svelte-motion'
</script>
<motion.div
initial={{ opacity: 0, y: 12 }}
animate={{ opacity: 1, y: 0 }}
transition={{ type: 'spring', stiffness: 320, damping: 24 }}
>
Migrated
</motion.div>Use motion.div, motion.button, and the other element proxies when API familiarity matters most. Use MotionDiv, MotionButton, and the named exports when you want the smallest tree-shaken surface.
Map the animation concepts
Most animation intent transfers directly:
svelte-motion concept | @humanspeak/svelte-motion equivalent |
|---|---|
Motion | motion.div or MotionDiv |
initial, animate, transition | The same prop names and semantics |
exit | exit inside AnimatePresence |
| Variants | Variants with parent-to-child propagation |
| Drag | Drag with constraints, momentum, elastic, and axis locking |
| Layout animation | layout and shared layoutId transitions |
The API reference lists the complete modern Framer Motion-style surface.
Migrate conditional exit animations
Elements cannot animate after Svelte removes them unless something owns their presence lifecycle. Wrap conditional content in AnimatePresence:
<script lang="ts">
import { AnimatePresence, motion } from '@humanspeak/svelte-motion'
let open = $state(true)
</script>
<AnimatePresence>
{#if open}
<motion.div
initial={{ opacity: 0, y: 12 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -12 }}
>Content</motion.div>
{/if}
</AnimatePresence><script lang="ts">
import { AnimatePresence, motion } from '@humanspeak/svelte-motion'
let open = $state(true)
</script>
<AnimatePresence>
{#if open}
<motion.div
initial={{ opacity: 0, y: 12 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -12 }}
>Content</motion.div>
{/if}
</AnimatePresence>Use mode="wait" for sequential replacement and mode="popLayout" when exiting items should immediately leave document flow. The live AnimatePresence example shows the modes in action.
Replace manual gesture state
Move transient hover, press, focus, and viewport animation into whileHover, whileTap, whileFocus, and whileInView. Try the hover and tap example and focus example.
Use layout animation instead of measuring boxes
Add layout when an element should animate between its old and new position or size. Use a matching layoutId across UI states to create a shared-element transition. See reordering and shared layout animation.
Move state to Svelte 5 runes
Keep application state in $state, compute targets with $derived, and use Motion values for continuously updating animation data:
useMotionValuestores an animatable value without forcing component rerenders.useSpringfollows another value with spring physics.useTransformmaps an input range into another value.useScrollsupplies page or element scroll progress.
The motion values guide explains when to use runes and when a Motion value is the better tool.
Verify the migration
Before removing the old package from your lockfile:
- Search for every import from
svelte-motion. - Verify conditional elements finish their exit animations.
- Test drag constraints and layout transitions at responsive breakpoints.
- Load animated routes directly in SvelteKit to exercise SSR and hydration.
- Test keyboard focus and the operating system’s reduced-motion preference.
- Check variants that rely on parent-to-child propagation.
The package requires Svelte 5 and does not provide a Svelte 4 compatibility layer. That sharper baseline enables its runes-native API, SSR behavior, and current Motion parity.
Start with the getting-started guide, then browse the live examples for the patterns used by your application.