# How to Make Elements Draggable with Animation in Anime.js

> Learn to make elements draggable with animation using Anime.js. Discover the createDraggable factory for physics-aware animations and real-time updates.

- Repository: [Julian Garnier/anime](https://github.com/juliangarnier/anime)
- Tags: tutorial
- Published: 2026-03-04

---

**Anime.js provides a dedicated `createDraggable` factory that converts any DOM element into a physics-aware draggable object powered by the internal `Animatable` class, enabling real-time coordinate updates, spring-based release animations, and seamless synchronization with timelines.**

The **juliangarnier/anime** library extends beyond traditional tweening with a complete drag-and-drop system built on its animation engine. Unlike standalone drag libraries, this implementation uses the same `Animatable` infrastructure found in [`src/animatable/animatable.js`](https://github.com/juliangarnier/anime/blob/main/src/animatable/animatable.js), allowing you to combine user-driven motion with programmatic effects. By importing `createDraggable` from [`dist/modules/index.js`](https://github.com/juliangarnier/anime/blob/main/dist/modules/index.js), you can make elements draggable while maintaining access to snapping, container bounds, and physics-based release behaviors.

## Understanding the Draggable Architecture

### Core Components

The draggable system relies on several interconnected classes that bridge user input with the animation engine:

- **`Draggable` class** – Defined in [`src/draggable/draggable.js`](https://github.com/juliangarnier/anime/blob/main/src/draggable/draggable.js) (line 219), this handles pointer events, computes velocity, manages container bounds, snapping, spring-based release, autoscroll, and cursor styling.
- **`createDraggable` factory** – A convenience exporter located at lines 281-287 in [`src/draggable/draggable.js`](https://github.com/juliangarnier/anime/blob/main/src/draggable/draggable.js) that instantiates and returns a configured `Draggable` object.
- **`Animatable` class** – Found in [`src/animatable/animatable.js`](https://github.com/juliangarnier/anime/blob/main/src/animatable/animatable.js) (line 41), this generic wrapper creates per-property animations that the `Draggable` manipulates during movement.
- **`createSpring`** – A helper exported from [`dist/modules/index.js`](https://github.com/juliangarnier/anime/blob/main/dist/modules/index.js) that generates spring easings for release animations.

When instantiated, a `Draggable` creates an internal `Animatable` instance stored in `this.animate`. This wrapper contains individual animations for each draggable property (`translateX`, `translateY`, etc.), accessible via calls like `this.animate[this.xProp](value, duration, ease)`.

### Event Flow and Update Cycle

The system processes user input through a strict pipeline that maintains synchronization with the animation engine:

1. **Pointer down** – `handleDown` records the start position, resets velocity, applies a high `z-index`, and disables page scrolling.
2. **Pointer move** – `handleMove` updates the internal pointer state and triggers `this.updateTicker`, which invokes the `update()` method.
3. **`update()` method** – Computes new coordinates, applies container friction, enforces bounds, updates the `Animatable` via `this.setX` and `this.setY`, and calculates velocity/angle.
4. **Pointer up** – `handleUp` calculates a release trajectory, optionally applies spring physics (`releaseXSpring`, `releaseYSpring`) or an easing function, then animates the target to its final resting point.

This pipeline triggers user-provided callbacks (`onGrab`, `onDrag`, `onRelease`, `onUpdate`, `onSnap`) at each phase, allowing real-time reactions to motion.

### Integration with the Animation Engine

Because `Draggable` internally uses an `Animatable`, you can treat draggable elements like standard animation targets. After initialization, you can programmatically animate properties:

```javascript
// Programmatically animate the draggable to a new position
draggable.animate[draggable.xProp](finalX, 500, 'outQuad');

```

Alternatively, use the high-level `animate` helper to modify other properties while the element remains draggable:

```javascript
import { animate } from 'animejs';

animate(draggable, {
  scale: 1.2,
  duration: 300,
  easing: 'outBack'
});

```

The instance also exposes `progressX` and `progressY` values normalized to container bounds (0 to 1), enabling binding to timeline animations or other effects.

## Creating a Basic Draggable Element

To make an element draggable, import `createDraggable` and pass a CSS selector or DOM element along with configuration options:

```html
<!DOCTYPE html>
<html>
<head>
  <style>
    .box { 
      width: 120px; 
      height: 120px; 
      background: #e91e63;
      border-radius: 8px; 
      cursor: grab; 
    }
  </style>
  <script type="module">
    import { createDraggable } from '../../dist/modules/index.js';

    createDraggable('#box', {
      container: document.body,
      snap: 20,
      cursor: { onHover: 'grab', onGrab: 'grabbing' },
      onDrag: d => console.log('velocity:', d.velocity.toFixed(2))
    });
  </script>
</head>
<body>
  <div id="box" class="box"></div>
</body>
</html>

```

**Key implementation details:**

- `createDraggable` automatically instantiates the internal `Animatable` wrapper.
- The `snap` option forces the target to land on multiples of 20 pixels.
- Cursor handling is built-in via the `cursor` configuration object.

## Implementing Advanced Drag Behaviors

### Adding Spring Physics to Release

For a natural throwing effect, configure the `releaseEase` property with a spring generated by `createSpring`:

```javascript
import { createDraggable, createSpring } from 'animejs';

const springEase = createSpring({
  mass: 1,
  stiffness: 300,
  damping: 20
});

createDraggable('#ball', {
  container: '#stage',
  releaseEase: springEase,
  maxVelocity: 80,
  onRelease: d => console.log('settled at', d.x, d.y)
});

```

When `handleUp` fires, the `Draggable` applies this spring to smoothly animate the element back into bounds or to its final resting point, with velocity capped by `maxVelocity`.

### Synchronizing Drag Progress with Timelines

You can bind the draggable's normalized position to timeline progress for scrubbing effects:

```javascript
import { createDraggable, createTimeline } from 'animejs';

const tl = createTimeline({ autoplay: false })
  .add('#bg', { opacity: [0, 1] }, 0)
  .add('#title', { translateY: [-50, 0] }, 0);

const drag = createDraggable('#thumb', {
  container: '#slider',
  y: false,
  snap: 10,
  onUpdate: d => { tl.progress = d.progressX; }
});

```

As the user drags horizontally across the container, `progressX` (ranging from 0 to 1) drives the timeline's progress, synchronizing the background fade and title slide with the thumb position.

## Summary

- **Use `createDraggable`** from [`src/draggable/draggable.js`](https://github.com/juliangarnier/anime/blob/main/src/draggable/draggable.js) to instantiate draggable elements with a single function call.
- **Internal `Animatable` integration** allows the `Draggable` class to reuse the standard animation engine for coordinate updates via `this.setX` and `this.setY`.
- **Event-driven architecture** processes input through `handleDown`, `handleMove`, `update()`, and `handleUp`, calculating velocity and enforcing bounds in real time.
- **Spring-based release** physics can be applied using `createSpring` and assigned to the `releaseEase` parameter for elastic throw effects.
- **Timeline synchronization** is possible by mapping `progressX` or `progressY` (normalized 0-1 values) to animation timelines or other properties.

## Frequently Asked Questions

### How do I constrain draggable movement to a specific container?

Pass a DOM element or CSS selector to the `container` property when calling `createDraggable`. The system automatically calculates bounds relative to this container and applies friction when the element approaches edges. If the element is thrown outside bounds, it springs back on release.

### Can I disable movement on one axis only?

Set the `x` or `y` property to `false` in the configuration object. For example, `y: false` restricts movement to horizontal dragging only, while still allowing the vertical position to be animated programmatically through the internal `Animatable`.

### How do I implement grid snapping?

Provide a number to the `snap` parameter, which specifies the pixel grid size. The `Draggable` instance automatically rounds coordinates to the nearest multiple of this value during the `update()` cycle, creating a stepped movement effect without manual calculation.

### What callbacks are available for reacting to drag events?

The system exposes `onGrab` (pointer down), `onDrag` (continuous movement), `onRelease` (pointer up), `onUpdate` (every frame), and `onSnap` (when snapping occurs). Each receives the draggable instance as an argument, providing access to `x`, `y`, `velocity`, and `progressX/Y` properties.