GSAP Draggable — Interactive Drag-and-Drop Elements
In this tutorial, you will learn about GSAP Draggable. We cover key concepts, practical examples, and best practices to help you master this topic.
GSAP Draggable enables mouse and touch-based dragging, throwing, snapping, and sorting for DOM elements with physics-based momentum.
What You'll Learn
By the end of this guide, you will create draggable elements with bounds and inertia, add throw physics for momentum scrolling, use snap points for grid alignment, build sortable drag-and-drop lists, handle drag events, and integrate with ScrollTrigger.
Basic Draggable
Draggable.create('.drag-box', {
type: 'x,y',
bounds: '.container',
inertia: true
});
Snap to Grid
Draggable.create('.grid-box', {
type: 'x,y',
snap: {
x: function(endValue) {
return Math.round(endValue / 50) * 50;
},
y: function(endValue) {
return Math.round(endValue / 50) * 50;
}
}
});
Drag Events
Draggable.create('.drag-box', {
type: 'rotation',
onDragStart: function() {
this.target.style.backgroundColor = '#ff6b35';
},
onDragEnd: function() {
this.target.style.backgroundColor = '#4ecdc4';
console.log('Final rotation:', this.rotation);
}
});
Sortable List
Draggable.create('.list-item', {
type: 'y',
bounds: '.list-container',
onDrag: function() {
var items = document.querySelectorAll('.list-item');
items.forEach(function(item, i) {
var y = item._gsTransform.y;
var index = Math.round(Math.abs(y) / 60);
if (index !== parseInt(item.dataset.index)) {
item.dataset.index = index;
}
});
}
});
Common Mistakes
1. Not Setting Bounds
Without bounds, elements can be dragged off-screen. Always set bounds to a container.
2. Type Mismatch
Using type: 'x,y' on an element with rotation transforms can cause unexpected behavior.
3. Inertia Without Throw
For momentum scrolling after release, set inertia: true. Without it, dragging stops immediately on release.
4. Snap Function Not Returning Value
The snap function must return a value. Returning undefined breaks snapping.
5. Touch Event Interference
Draggable handles touch by default. If other touch handlers conflict, use Draggable.zIndexBoost.
Practice Questions
Q1: What types of drag are supported? A: 'x', 'y', 'x,y', 'rotation', 'scroll', and 'scrollTop'.
Q2: How do you add momentum after release? A: Set inertia: true in the Draggable config.
Q3: How do you restrict drag to a container? A: Set bounds: '.container' or bounds: { minX: 0, maxX: 300 }.
Q4: What event fires when drag starts? A: onDragStart fires when the user begins dragging.
Q5: How do you get the current position? A: Access this.x and this.y inside event callbacks, or this.target._gsTransform.
Challenge: Build a puzzle where pieces snap to a grid. When all pieces are in correct positions, trigger a completion animation.
FAQ
Try It Yourself
Create a draggable box with snap.
<!DOCTYPE html>
<html>
<head>
<title>GSAP Draggable Demo</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12/gsap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12/Draggable.min.js"></script>
<style>
.container { width: 400px; height: 300px; border: 2px dashed #ccc; border-radius: 8px; position: relative; }
.drag-box { width: 60px; height: 60px; background: #4ecdc4; border-radius: 8px; cursor: grab; position: absolute; display: flex; align-items: center; justify-content: center; color: white; font-weight: bold; }
.drag-box:active { cursor: grabbing; }
.drag-box:nth-child(2) { background: #ff6b35; left: 100px; }
.drag-box:nth-child(3) { background: #2a9d8f; left: 200px; }
</style>
</head>
<body style="font-family:sans-serif;padding:20px;">
<h2>Draggable with Snap</h2>
<button onclick="resetPositions()">Reset</button>
<div class="container" id="container">
<div class="drag-box" id="box1">1</div>
<div class="drag-box" id="box2">2</div>
<div class="drag-box" id="box3">3</div>
</div>
<script>
Draggable.create('.drag-box', {
type: 'x,y',
bounds: '#container',
inertia: true,
snap: {
x: function(v) { return Math.round(v / 50) * 50; },
y: function(v) { return Math.round(v / 50) * 50; }
}
});
function resetPositions() {
gsap.set('#box1', { x: 0, y: 0 });
gsap.set('#box2', { x: 100, y: 0 });
gsap.set('#box3', { x: 200, y: 0 });
}
</script>
</body>
</html>
What's Next
Animate text content.
Text Plugin — Text animation plugin. CSS Plugin — CSS properties plugin.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro