webdevpuneet.com

Draggable Throw Notes — Free GSAP Inertia Snippet

Draggable Throw Notes · Cards · Plain HTML, CSS & JS · Live preview

CategoryCards

Copy & paste

Source Code

<div class="dtn-board" id="dtnBoard">
  <p class="dtn-hint">Drag a note and let go with speed — it keeps moving and settles inside the board.</p>
  <div class="dtn-note" style="--nc:#fde68a;--nr:-3deg;left:8%;top:18%">
    <b>Ship it 🚀</b>
    <span>Flick me across the board.</span>
  </div>
  <div class="dtn-note" style="--nc:#a7f3d0;--nr:2.5deg;left:42%;top:48%">
    <b>Physics ✨</b>
    <span>Momentum comes from InertiaPlugin.</span>
  </div>
  <div class="dtn-note" style="--nc:#bfdbfe;--nr:-1.5deg;left:66%;top:22%">
    <b>Bounds 🧲</b>
    <span>I can't escape the corkboard.</span>
  </div>
</div>

Extend with AI

Take This Snippet Further With AI

The AI prompt for this one is for Patreon supporters ($3 a month), along with a site with no ads. Supporters enter the passcode once and it is remembered in this browser.

· Become a supporter

What's included

Features

Real momentum
Release velocity becomes a natural glide.
Bounds-aware throws
End positions are solved inside the board.
Rubber-band edges
edgeResistance damps over-drag by 72%.
Grab choreography
Lift, square-up, and z-index on press.
Messy-by-design
random(-4,4) rotation on every release.
Input-normalized
Mouse, touch, and pointer in one config.
Mobile-correct
touch-action: none beats page scrolling.
Transform-driven
Drags and glides are compositor-only.

About this UI Snippet

Draggable Throw Notes — Momentum Dragging With GSAP’s InertiaPlugin

Screenshot of the Draggable Throw Notes snippet rendered live

Plain HTML5 drag feels dead: the element stops the instant your pointer does. These sticky notes feel alive — grab one, flick it, and it keeps traveling with realistic momentum before gliding to a stop, always inside the corkboard. That's GSAP's Draggable paired with InertiaPlugin (both free on the CDN since GSAP 3.13), which together replace an entire physics-and-input layer with one Draggable.create() call.

inertia: true is where the physics lives

Draggable continuously tracks pointer velocity while you drag. On release, inertia: true hands that velocity to InertiaPlugin, which computes a natural deceleration curve — how far the note *would* slide given friction — and tweens it there. Crucially, the plugin solves the end position *first*: it knows the note's destination the moment you let go, which is why it can guarantee the landing spot respects bounds instead of clamping mid-flight with an ugly wall-stop.

bounds turns the board into a container, not a cage wall

bounds: '#dtnBoard' constrains both dragging and thrown travel to the board's box. During an over-drag past the edge, edgeResistance: 0.72 makes the note move only ~28% of your pointer's distance — the rubbery tension every native app uses to say "you've hit the edge" — and on release it settles back inside. A thrown note aimed at the edge decelerates to land exactly at the boundary, because InertiaPlugin factored the bounds into its end-point solve.

Grab feedback is choreography, not physics

onPress bumps the note's z-index above its siblings (an incrementing counter, so the most recently touched note always wins) and animates a 1.06 scale with rotation zeroed — the note "lifts off the board" and squares up in your hand. onRelease settles it back down with a fresh random(-4, 4) rotation, so every throw leaves the board looking naturally messy rather than snapping notes back to fixed angles. GSAP's string-based random() makes that one line.

touch-action: none is the mobile linchpin

Each note sets touch-action: none so mobile browsers hand the touch to Draggable instead of scrolling the page — without it, vertical flicks would scroll instead of throw. Draggable normalizes mouse, touch, and pointer events internally, so the one config works everywhere, including the user-select: none needed to stop text selection during fast drags.

Transforms only, so throws stay smooth

Draggable moves elements via x/y transforms (not left/top), so dragging and inertia glides are compositor work. The CSS positions notes initially with left/top percentages purely for layout convenience; Draggable layers transforms on top from then on.

Where you'd take it further

Real boards persist positions (write this.x / this.y to storage in onThrowComplete), add snap to align notes to a grid, or set throwResistance to tune how far flicks travel. For rotation-based dragging, see the drag spin dial; for pointer-ordered lists, drag sort list; for scroll-driven momentum instead, drag scroll row; and for resizable workspaces, drag resize panels.

Step by step

How to Use

  1. 1
    Add the GSAP CDNsInclude gsap, Draggable, and InertiaPlugin from the CDN panel.
  2. 2
    Paste HTML, CSS, and JSThree sticky notes render pinned to a corkboard.
  3. 3
    Grab a noteIt lifts, squares up, and jumps above its siblings.
  4. 4
    Flick and releaseMomentum carries it to a natural stop inside bounds.
  5. 5
    Push past an edgeRubbery resistance, then it settles back in.
  6. 6
    Tune the feeledgeResistance and throwResistance set the physics.

Real-world uses

Common Use Cases

Brainstorm boards
Let teams move idea notes freely and flick them across a corkboard, then make them orderable with a drag sort list when order starts to matter.
Mood boards for creative tools
Offer tossable image cards, placed near a masonry grid, with release velocity turning into a natural glide that stays inside the board.
Playful 404 pages and heroes
Add interactive props that visitors can fling around, alongside physics balls, with edge resistance damping any over-drag by 72 percent.
Kanban prototypes
Test momentum-dragged cards before wiring up a real kanban board, with lift, square-up and z-index changes on press.
Rotation and swipe relatives
Compare with inertia applied to knobs in a drag spin dial, or velocity-based dismissal in swipe cards.
Related: Motion One Spring Cards
See the Motion One Spring Cards for a related cards pattern worth pairing with this one.

Got questions?

Frequently Asked Questions

Draggable tracks your pointer's velocity throughout the drag; with inertia: true, that velocity is handed to InertiaPlugin on release, which computes a natural deceleration tween. It solves the final resting position up front — factoring in bounds — then animates there, which is why throws glide to elegant stops instead of hitting invisible walls.

It damps over-drag: at 0.72, once your pointer crosses the board's boundary the note follows only 28% of the pointer's movement, producing the rubber-band tension native apps use to signal an edge. On release the note animates back inside bounds. Set it to 1 for a hard wall or 0 to allow free dragging outside.

Because on touch devices the browser defaults to interpreting vertical drags as page scrolling. touch-action: none tells the browser this element handles its own gestures, so flicks reach Draggable instead of scrolling. Combined with user-select: none (preventing text selection mid-drag), it's the difference between a demo that works on desktop and one that works everywhere.

An incrementing z counter: onPress assigns ++z to the grabbed note's z-index, so each grab claims a value higher than every previous one. It's simpler and cheaper than re-sorting siblings, and it matches physical intuition — whatever you touched last is the note sitting highest on the pile.

Yes — pass snap: { x: value => Math.round(value / 40) * 40, y: same } and InertiaPlugin will target the nearest snap point when solving the throw's end position, so notes glide into alignment rather than stopping arbitrarily. An array of pixel values works too for fixed slots, and liveSnap: true snaps during the drag itself.

Create the Draggable instances in a mount effect — useEffect, onMounted, or ngAfterViewInit — from a container ref, and call .kill() on each instance (or revert a gsap.context) in the cleanup so listeners detach on unmount. Register both plugins once at module scope. To persist positions, read this.x/this.y in onThrowComplete into state or storage; note styling maps directly to Tailwind utilities.