Skip to main content

motion

The motion proxy drives most animations in Motion Start.

motion is a proxy: every HTML and SVG element is available on it as motion.div, motion.button, motion.circle, and so on. A motion component behaves exactly like its plain counterpart — same attributes, same events — plus animation props.

		<script>
	import { motion } from "motion-start";
</script>
 
<motion.div
	initial={{ opacity: 0 }}
	animate={{ opacity: 1 }}
	exit={{ opacity: 0 }}
	whileHover={{ scale: 1.05 }}
	transition={{ type: "spring" }}
/>
	
hover me
rotate
tap me

Animation props

initial
type: Target | VariantLabels | false
The state the component mounts in. `false` skips the mount animation.
animate
type: Target | VariantLabels | AnimationControls
The state to animate towards whenever it changes.
exit
type: Target | VariantLabels
The state to animate to before unmounting. Requires an `AnimatePresence` ancestor.
transition
type: Transition
How values animate. See [Transitions](/docs/animation/transitions).
variants
type: Variants
Named animation targets, so labels can be used instead of objects — and inherited by children.
style
type: MotionStyle
Like `style`, but transform shorthands (`x`, `y`, `scale`, `rotate`) and `MotionValue`s are accepted.

Server rendering and pre-hydration animation

Motion components include their resolved initial styles in server-rendered HTML. This prevents the element from flashing its unanimated state before Svelte hydrates.

Set appear to start eligible entrance animations as the browser parses the HTML, without waiting for Svelte hydration:

		<motion.div
	appear
	initial={{ opacity: 0, y: 20 }}
	animate={{ opacity: 1, y: 0 }}
	transition={{ type: "tween", duration: 0.4, ease: "easeOut" }}
/>
	

appear is a Motion Start extension. It applies to HTML elements whose target and transition can be resolved on the server, with an explicit tween or keyframes transition. Every value in animate must also be present in initial, since there is no computed style to read from before hydration.

Springs, dynamic variant functions, transformTemplate, SVG elements, custom components, CSS custom properties, per-value transitions, repeats, orchestration options (when, delayChildren, staggerChildren) and client-side navigations all fall back to the normal hydration-time animation. The parser-time animation hands off to Motion during hydration without restarting.

Omitting ease is supported: the parser-time animation uses Motion's default easeOut curve. MotionConfig reduced-motion settings are respected; "user" suppresses parser-time transform animations when the visitor prefers reduced motion.

For a Content Security Policy that requires nonces, pass the nonce through appear:

		<motion.div
	appear={{ nonce }}
	initial={{ opacity: 0 }}
	animate={{ opacity: 1 }}
	transition={{ type: "tween", duration: 0.3 }}
/>
	

Gesture props

whileHover, whileTap, whileFocus, whileDrag and whileInView, plus their event handlers. See Gestures.

Layout props

layout, layoutId, layoutDependency, layoutRoot and layoutScroll. See Layout animations.

Lifecycle events

onAnimationStart
type: (definition) => void
onAnimationComplete
type: (definition) => void
onUpdate
type: (latest: ResolvedValues) => void

Transform shorthands

Transforms are independent values, so they can be animated separately and composed without fighting over a single transform string.

		<motion.div style={{ x: 100, rotate: 45, scale: 1.2 }} />
	

Available: x, y, z, translateX/Y/Z, scale, scaleX/Y, rotate, rotateX/Y/Z, skew, skewX/Y, originX/Y/Z, perspective.

SVG

SVG elements work the same way, including pathLength, pathSpacing and pathOffset, which are normalised to 0–1.

		<motion.path initial={{ pathLength: 0 }} animate={{ pathLength: 1 }} />
	

The m component

m is the same component with no features bundled in. Paired with LazyMotion it keeps the initial bundle small.

		<script>
	import { m } from "motion-start/m";
</script>
 
<m.div animate={{ opacity: 1 }} />