Skip to main content

Overview

The drag gesture allows elements to be dragged with pointer or touch input. Dragging can be enabled on both axes, or locked to a single axis, with constraints and momentum support.

Props

drag

Enable dragging for the element.
type drag = boolean | "x" | "y"
  • false (default): Dragging is disabled
  • true: Drag in both directions
  • "x": Drag only horizontally
  • "y": Drag only vertically
<motion.div drag="x" />

dragConstraints

Applies constraints on the permitted draggable area.
type dragConstraints = false | Partial<BoundingBox> | RefObject<Element>

interface BoundingBox {
  top?: number
  right?: number
  bottom?: number
  left?: number
}
Can accept an object of optional top, left, right, and bottom values (in pixels), or a ref to another element.
// In pixels
<motion.div
  drag="x"
  dragConstraints={{ left: 0, right: 300 }}
/>

// As a ref to another component
const constraintsRef = useRef(null)

<motion.div ref={constraintsRef">
  <motion.div drag dragConstraints={constraintsRef} />
</motion.div>

dragElastic

The degree of movement allowed outside constraints.
type dragElastic = boolean | number | Partial<BoundingBox>
  • 0: No movement outside constraints
  • 1: Full movement
  • Default: 0.5
Can also be set as false to disable, or as an object with top/right/bottom/left values.
<motion.div
  drag
  dragConstraints={{ left: 0, right: 300 }}
  dragElastic={0.2}
/>

dragMomentum

Apply momentum from the pan gesture when dragging finishes.
type dragMomentum = boolean // default: true
<motion.div
  drag
  dragConstraints={{ left: 0, right: 300 }}
  dragMomentum={false}
/>

dragTransition

Customize the drag inertia animation.
type dragTransition = InertiaOptions

interface InertiaOptions {
  bounceStiffness?: number
  bounceDamping?: number
  power?: number
  timeConstant?: number
  restDelta?: number
  modifyTarget?: (v: number) => number
}
<motion.div
  drag
  dragTransition={{ bounceStiffness: 600, bounceDamping: 10 }}
/>

dragDirectionLock

Lock dragging to the initially-detected direction.
type dragDirectionLock = boolean // default: false
<motion.div drag dragDirectionLock />

dragPropagation

Allow drag gesture propagation to child components.
type dragPropagation = boolean // default: false
<motion.div drag="x" dragPropagation />

dragControls

Manually control the drag gesture using useDragControls().
type dragControls = DragControls
const dragControls = useDragControls()

function startDrag(event) {
  dragControls.start(event, { snapToCursor: true })
}

return (
  <>
    <div onPointerDown={startDrag} />
    <motion.div drag="x" dragControls={dragControls} />
  </>
)

dragListener

Enable/disable automatic drag initiation on pointer down.
type dragListener = boolean // default: true
<motion.div
  drag="x"
  dragControls={dragControls}
  dragListener={false}
/>

dragSnapToOrigin

Snap back to origin when dragging ends.
type dragSnapToOrigin = boolean // default: false
<motion.div drag dragSnapToOrigin />

whileDrag

Properties or variant label to animate to while dragging.
type whileDrag = VariantLabels | TargetAndTransition
<motion.div drag whileDrag={{ scale: 1.2 }} />

Event Handlers

onDragStart

Callback when dragging starts.
type onDragStart = (
  event: MouseEvent | TouchEvent | PointerEvent,
  info: PanInfo
) => void

interface PanInfo {
  point: { x: number; y: number }
  delta: { x: number; y: number }
  offset: { x: number; y: number }
  velocity: { x: number; y: number }
}
<motion.div
  drag
  onDragStart={(event, info) => console.log(info.point.x, info.point.y)}
/>

onDrag

Callback while the component is being dragged.
type onDrag = (
  event: MouseEvent | TouchEvent | PointerEvent,
  info: PanInfo
) => void
<motion.div
  drag
  onDrag={(event, info) => console.log(info.point.x, info.point.y)}
/>

onDragEnd

Callback when dragging ends.
type onDragEnd = (
  event: MouseEvent | TouchEvent | PointerEvent,
  info: PanInfo
) => void
<motion.div
  drag
  onDragEnd={(event, info) => console.log(info.velocity.x, info.velocity.y)}
/>

onDirectionLock

Callback when drag direction is determined (when dragDirectionLock is enabled).
type onDirectionLock = (axis: "x" | "y") => void
<motion.div
  drag
  dragDirectionLock
  onDirectionLock={axis => console.log(axis)}
/>

onDragTransitionEnd

Callback when drag momentum/bounce transition finishes.
type onDragTransitionEnd = () => void
<motion.div
  drag
  onDragTransitionEnd={() => console.log('Drag transition complete')}
/>

onMeasureDragConstraints

Callback with the measured drag constraints (when using a ref).
type onMeasureDragConstraints = (
  constraints: BoundingBox
) => BoundingBox | void
<motion.div
  drag
  dragConstraints={constraintsRef}
  onMeasureDragConstraints={(constraints) => {
    return {
      ...constraints,
      left: constraints.left + 100
    }
  }}
/>

Build docs developers (and LLMs) love