Beta Status

This library is still in early beta and the API is subject to change and may get daily breaking changes. The documentaton may not be up to date with the latest features and include missing or outdated information. You can always create an issue on GitHub or even better a pull request to fix the documentation or add new features.

Motion Component

The motion proxy exposes a component for every HTML and SVG element. Motion components accept all native props plus animation-specific props.

import { motion } from "motion-solid";

// HTML elements
<motion.div />
<motion.button />
<motion.section />

// SVG elements
<motion.svg />
<motion.path />
<motion.circle />

Basic Example

<motion.div
  class="card"
  initial={{ opacity: 0, y: 20 }}
  animate={{ opacity: 1, y: 0 }}
  transition={{ duration: 0.4, ease: "ease-out" }}
>
  Fade in from below
</motion.div>

Animation Props

initial

The starting state. Can be an animation target, a variant label, or false to skip the initial animation.

// Animation target
<motion.div initial={{ opacity: 0, scale: 0.8 }} />

// Variant label
<motion.div initial="hidden" variants={variants} />

// Skip initial animation
<motion.div initial={false} animate={{ x: 100 }} />

animate

Target to animate to on mount and when props change. Can be a target object, variant label, or array of labels.

// Animation target
<motion.div animate={{ opacity: 1, x: 50 }} />

// Variant label
<motion.div animate="visible" variants={variants} />

// Multiple variants (merged in order)
<motion.div animate={["visible", "highlight"]} variants={variants} />

// CSS custom properties
<motion.div animate={{ "--progress": 0.5, "--color": "#ff0000" }} />

exit

Target to animate to when the component leaves. Requires AnimatePresence.

<AnimatePresence>
  <Show when={visible()}>
    <motion.div
      initial={{ opacity: 0 }}
      animate={{ opacity: 1 }}
      exit={{ opacity: 0, y: -20 }}
    />
  </Show>
</AnimatePresence>

transition

Controls how values animate. Can be set per-prop or as a default.

// Default for all values
<motion.div
  animate={{ x: 100, opacity: 1 }}
  transition={{ type: "spring", stiffness: 200 }}
/>

// Per-prop overrides
<motion.div
  animate={{ x: 100, opacity: 1 }}
  transition={{
    x: { type: "spring" },
    opacity: { duration: 0.2 },
  }}
/>

// Using transitionEnd for final values
<motion.div
  animate={{ opacity: 1 }}
  transition={{ transitionEnd: { display: "none" } }}
/>

Transition types:

  • "spring" - Physics-based with stiffness, damping, mass
  • "tween" - Duration-based with duration, ease
  • "keyframes" - Step through an array of values
  • "inertia" - Decelerate from initial velocity

variants

Map of named animation targets. See Variants.

const variants = {
  hidden: { opacity: 0 },
  visible: { opacity: 1 },
};

<motion.div variants={variants} initial="hidden" animate="visible" />;

custom

Data passed to variant functions. Also provided by AnimatePresence.

const variants = {
  visible: (delay: number) => ({
    opacity: 1,
    transition: { delay },
  }),
};

<motion.div variants={variants} custom={0.2} animate="visible" />;

inherit

Set to false to prevent inheriting variants from ancestors.

<motion.ul variants={list} animate="show">
  <motion.li variants={item} /> {/* inherits "show" */}
  <motion.li inherit={false} /> {/* does not inherit */}
</motion.ul>

Style

Regular Solid style object, merged with animated values. Use kebab-case for CSS and transform properties (scale-x, rotate-y, etc).

<motion.div style={{ "background-color": "blue" }} animate={{ x: 100 }} />

Lifecycle Callbacks

onUpdate

Called on every render with the latest values:

<motion.div animate={{ x: 100 }} onUpdate={(latest) => console.log(latest.x)} />

onAnimationStart / onAnimationComplete

Fired when the animate target starts or finishes:

<motion.div
  animate={{ opacity: 1 }}
  onAnimationStart={() => console.log("started")}
  onAnimationComplete={() => console.log("done")}
/>

Gestures and Drag

Motion supports gesture animations and callbacks:

  • whileHover - Animation while hovering
  • whileTap - Animation while pressing
  • whileFocus - Animation while focused
  • whileInView - Animation when in viewport
  • whileDrag - Animation while dragging

See Gestures and Drag for details.

<motion.button
  whileHover={{ scale: 1.05 }}
  whileTap={{ scale: 0.95 }}
  onTap={() => console.log("clicked")}
/>

Layout

Enable layout animations with layout or layoutId:

// Animate position and size changes
<motion.div layout />

// Shared element transitions
<motion.div layoutId="sidebar" />

See Layout for details.

Server-Side Rendering

On the server, motion components render with deterministic styles:

  • Uses initial styles if provided
  • Uses animate styles if initial is false or undefined
// Server renders with opacity: 0
<motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} />

// Server renders with opacity: 1
<motion.div initial={false} animate={{ opacity: 1 }} />

Limitations

  • Custom components via motion(Component) are not supported yet
  • MotionValue in style prop is planned