Core React components that wrap DOM elements with animation capabilities. Motion components support declarative animations through props and can be used with all HTML and SVG elements.
The motion object provides enhanced versions of all HTML and SVG elements with animation capabilities.
/**
* Enhanced React components with animation capabilities for all HTML elements
*/
const motion: {
[K in keyof HTMLElementTagNameMap]: React.ForwardRefExoticComponent<
HTMLMotionProps<K>
>;
} & {
[K in keyof SVGElementTagNameMap]: React.ForwardRefExoticComponent<
SVGMotionProps<SVGElement>
>;
} & {
/**
* Create a custom motion component from any React component
* @param Component - Component to enhance with motion capabilities
* @returns Enhanced component with MotionProps
*/
create<Props>(
Component: string | React.ComponentType<Props>
): React.ForwardRefExoticComponent<MotionProps & Props>;
};Available Elements:
motion.div, motion.span, motion.button, motion.input, motion.img, etc. (all HTML elements)motion.svg, motion.circle, motion.path, motion.rect, motion.g, etc. (all SVG elements)Usage Examples:
import { motion } from "framer-motion";
// Basic HTML element with animation
<motion.div
initial={{ opacity: 0, scale: 0.8 }}
animate={{ opacity: 1, scale: 1 }}
transition={{ duration: 0.5 }}
>
Animated content
</motion.div>
// SVG element with animation
<motion.svg width="100" height="100">
<motion.circle
cx="50"
cy="50"
r="20"
fill="blue"
animate={{ r: [20, 30, 20] }}
transition={{ duration: 2, repeat: Infinity }}
/>
</motion.svg>
// Custom component with motion
const MotionCard = motion.create(Card);
<MotionCard
whileHover={{ y: -10 }}
transition={{ type: "spring" }}
/>The m object provides the same components as motion but designed for use with LazyMotion for code splitting.
/**
* Minimal motion components for use with LazyMotion feature bundles
*/
const m: typeof motion;Usage with LazyMotion:
import { LazyMotion, domAnimation, m } from "framer-motion";
function App() {
return (
<LazyMotion features={domAnimation}>
<m.div
animate={{ x: 100 }}
transition={{ type: "spring" }}
>
Animated with lazy-loaded features
</m.div>
</LazyMotion>
);
}All motion components support these core animation properties:
interface MotionProps {
/**
* Initial animation state when component mounts
*/
initial?: boolean | Variant;
/**
* Animation to perform when component is in view
*/
animate?: AnimationControls | Variant;
/**
* Animation to perform when component unmounts (requires AnimatePresence)
*/
exit?: Variant;
/**
* Transition configuration for animations
*/
transition?: Transition;
/**
* Named animation variants for reuse
*/
variants?: Variants;
/**
* Animation while element is hovered
*/
whileHover?: Variant;
/**
* Animation while element is pressed/tapped
*/
whileTap?: Variant;
/**
* Animation while element is focused
*/
whileFocus?: Variant;
/**
* Animation while element is being dragged
*/
whileDrag?: Variant;
/**
* Animation while element is in view
*/
whileInView?: Variant;
}Motion components include built-in gesture handling:
interface GestureProps {
/**
* Enable dragging. Can be boolean or axis-specific
*/
drag?: boolean | "x" | "y";
/**
* Define drag boundaries
*/
dragConstraints?: Partial<BoundingBox2D> | React.RefObject<Element>;
/**
* Enable drag momentum and inertia
*/
dragMomentum?: boolean;
/**
* Drag event handlers
*/
onDragStart?: (event: MouseEvent | TouchEvent | PointerEvent, info: PanInfo) => void;
onDrag?: (event: MouseEvent | TouchEvent | PointerEvent, info: PanInfo) => void;
onDragEnd?: (event: MouseEvent | TouchEvent | PointerEvent, info: PanInfo) => void;
/**
* Hover event handlers
*/
onHoverStart?: (event: MouseEvent, info: EventInfo) => void;
onHoverEnd?: (event: MouseEvent, info: EventInfo) => void;
/**
* Tap event handlers
*/
onTap?: (event: MouseEvent | TouchEvent | PointerEvent, info: TapInfo) => void;
onTapStart?: (event: MouseEvent | TouchEvent | PointerEvent, info: TapInfo) => void;
onTapCancel?: (event: MouseEvent | TouchEvent | PointerEvent, info: TapInfo) => void;
}
interface PanInfo {
point: Point;
delta: Point;
offset: Point;
velocity: Point;
}
interface Point {
x: number;
y: number;
}
interface BoundingBox2D {
top: number;
right: number;
bottom: number;
left: number;
}Props for automatic layout animations:
interface LayoutProps {
/**
* Enable automatic layout animations on size/position changes
*/
layout?: boolean | "position" | "size";
/**
* Unique ID for shared layout animations
*/
layoutId?: string;
/**
* Root element for layout calculations
*/
layoutRoot?: boolean;
/**
* Enable layout animations during scroll
*/
layoutScroll?: boolean;
/**
* Dependency array for when to trigger layout animations
*/
layoutDependency?: any;
}Event callbacks for animation lifecycle:
interface AnimationEventHandlers {
/**
* Called when any animation starts
*/
onAnimationStart?: (definition: AnimationDefinition) => void;
/**
* Called when any animation completes
*/
onAnimationComplete?: (definition: AnimationDefinition) => void;
/**
* Called on every animation frame update
*/
onUpdate?: (latest: ResolvedValues) => void;
/**
* Called when layout animation starts
*/
onLayoutAnimationStart?: () => void;
/**
* Called when layout animation completes
*/
onLayoutAnimationComplete?: () => void;
}
type AnimationDefinition = string | {
[key: string]: any;
};
interface ResolvedValues {
[key: string]: string | number;
}Type definitions for HTML and SVG motion components:
/**
* Props for HTML motion components
*/
type HTMLMotionProps<T extends keyof HTMLElementTagNameMap> = Omit<
React.HTMLProps<HTMLElementTagNameMap[T]>,
"ref" | "style"
> &
MotionProps &
GestureProps &
LayoutProps &
AnimationEventHandlers & {
/**
* Enhanced style prop supporting motion values
*/
style?: MotionStyle;
};
/**
* Props for SVG motion components
*/
type SVGMotionProps<T> = Omit<React.SVGProps<T>, "ref" | "style"> &
MotionProps &
GestureProps &
LayoutProps &
AnimationEventHandlers & {
/**
* Enhanced style prop supporting motion values
*/
style?: MotionStyle;
};
/**
* Enhanced CSS properties supporting motion values and transforms
*/
interface MotionStyle extends Omit<React.CSSProperties, "rotate" | "scale" | "perspective"> {
x?: string | number | MotionValue<number | string>;
y?: string | number | MotionValue<number | string>;
z?: string | number | MotionValue<number | string>;
rotate?: string | number | MotionValue<number | string>;
rotateX?: string | number | MotionValue<number | string>;
rotateY?: string | number | MotionValue<number | string>;
rotateZ?: string | number | MotionValue<number | string>;
scale?: string | number | MotionValue<number | string>;
scaleX?: string | number | MotionValue<number | string>;
scaleY?: string | number | MotionValue<number | string>;
scaleZ?: string | number | MotionValue<number | string>;
skew?: string | number | MotionValue<number | string>;
skewX?: string | number | MotionValue<number | string>;
skewY?: string | number | MotionValue<number | string>;
originX?: string | number | MotionValue<number | string>;
originY?: string | number | MotionValue<number | string>;
originZ?: string | number | MotionValue<number | string>;
perspective?: string | number | MotionValue<number | string>;
transformPerspective?: string | number | MotionValue<number | string>;
}Basic Animations:
<motion.div
initial={{ opacity: 0, y: 50 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -50 }}
transition={{
duration: 0.5,
ease: "easeOut"
}}
>
Basic animation
</motion.div>Gesture Interactions:
<motion.button
whileHover={{ scale: 1.1 }}
whileTap={{ scale: 0.95 }}
whileFocus={{ boxShadow: "0 0 0 3px rgba(59, 130, 246, 0.5)" }}
drag
dragConstraints={{ left: 0, right: 300, top: 0, bottom: 300 }}
onDragEnd={(event, info) => {
console.log("Drag ended at:", info.point);
}}
>
Interactive button
</motion.button>Layout Animations:
<motion.div
layout
layoutId="shared-element"
transition={{ type: "spring", stiffness: 300, damping: 30 }}
>
Automatically animates layout changes
</motion.div>Variants System:
const variants = {
hidden: { opacity: 0, scale: 0.8 },
visible: {
opacity: 1,
scale: 1,
transition: {
duration: 0.5,
ease: "easeOut"
}
}
};
<motion.div
variants={variants}
initial="hidden"
animate="visible"
>
Using variants
</motion.div>