Skip to content

Elastic Overscroll List

Rubber-band overscroll with the real asymptotic curve, engaged only at the boundary.

Prominimalplayful
Category
Animations
Added
2026-09-21
Deps
none
Updated
2026-09-21

This is a viberdy Pro component

The live preview, the props panel and the write-up are open to everyone. The full source, the AI prompt and CLI install are part of Pro.

Preview
  • Shell parka — olive01
  • Wool topcoat — charcoal02
  • Field jacket — sand03
  • Down liner — black04
  • Fisherman rib — ecru05
  • Merino crew — navy06
  • Cashmere half-zip — fog07
  • Pleated wool — ink08
  • Carpenter twill — stone09
  • Selvedge denim — raw10
drag past either end

Props

0.55
460
No runtime dependencies
"use client";

import { useRef } from "react";

/**
 * Rubber-band overscroll for a scroll container, for the platforms and
 * containers that do not get it for free: Android, Windows, and anywhere you
 * have set overscroll-behavior to stop the gesture chaining to the page.
 */

/**
 * THE APPLE RUBBER-BAND FUNCTION.
 *
 *   f(x) = (x * d * c) / (d + c * |x|)
 *
 * where d is the container's size and c is roughly 0.55. It is asymptotic: as
 * the drag grows the travel approaches d and never exceeds it, so resistance
 * rises continuously and the limit is never actually reached.

  // ---------------------------------------------------------------
  // Full source available with a viberdy Pro subscription.
  // https://viberdy.dev/pricing
  // ---------------------------------------------------------------
}
Notes

About this animation

The bounce at the end of an iOS scroll is one curve, and substituting a linear multiplier with a clamp is why most reimplementations feel wrong rather than merely different. The real function divides the drag by a term that grows with the drag, which makes it asymptotic: travel approaches the container's own size and never passes it, resistance rises continuously, and the limit is never actually reached. A clamped linear version hits its maximum almost immediately, so the last two thirds of the gesture produce no response at all — the curve is the effect. Three implementation details decide whether it feels attached to the content. The rubber band engages only when the container is already at a boundary and the drag pushes further, because applying the transform on every move fights the container's own scrolling and the list stutters as the two disagree. The transform is applied to the inner content rather than to the scroller, since transforming a scroll container makes it a containing block for fixed descendants and interferes with its own scrolling. And a new drag reads the current translate off the computed style and reapplies it without a transition, or the content jumps from wherever the previous spring had reached.

Curator’s note

Linear travel with a clamp is the usual stand-in and it feels dead — you reach the clamp instantly and the rest of the gesture does nothing.

Related

Pairs well with

Matched on shared tags and category — the entries most likely to be used alongside this one.

Pro

Reveals text one line at a time, each sliding up from behind its own clipping mask.

text-revealmaskscroll
Pro

A wrapper that reveals its children one after another as the group scrolls into view.

staggerrevealscroll
Featured
New

A depth system where layers separate under the pointer from one shared motion source.

parallaxpointerdepth