dom-autoscroller

A lightweight JavaScript library that auto-scrolls DOM containers when the pointer nears their edges, built for drag-and-drop interactions.

Library
npm
v2.3.4
80stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
29/100Needs Attention
Development Activity0
Maintenance0
Community44
Maturity60
Momentum12

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
50/100Fair
Architecture58
Code Quality40
Innovation45
Learning Curve55

dom-autoscroller solves a narrow but common UI problem: when a user drags an item toward the edge of a scrollable container, the container should scroll to reveal more content, but plain HTML gives you no such behavior for free. The library watches pointer and touch movement across the whole window, figures out which registered element the pointer is currently over or near, and drives that element’s scroll position with a speed that ramps up the closer the pointer gets to the edge.

It was built specifically to pair with drag-and-drop libraries like dragula, but it has no hard dependency on any particular drag implementation — it only needs to know when a drag is active via a user-supplied autoScroll callback. The API is a single factory function that accepts one element, an array of elements, or the window itself, plus an options object for margin size, max speed, and whether scrolling continues once the pointer leaves the container.

What You Get

  • A single autoScroll(elements, options) factory that wires up scrolling on one element, an array of elements, or the window
  • Distance-based speed ramping — scroll speed increases the closer the pointer gets to the container edge, capped by maxSpeed
  • A destroy() method that tears down all window-level event listeners cleanly, with an optional flag to force-stop any in-flight scroll animation
  • Undocumented add()/remove() methods for dynamically changing which elements are being watched after initialization
  • A syncMove option that re-dispatches synthetic mousemove events during auto-scroll so other pointer-driven code stays in sync with the new coordinates
  • Built as an ES module with a pre-built UMD/browserify-compatible bundle in dist/, so it drops into either a bundler-based project or a plain <script> tag

Common Use Cases

  • Auto-scrolling a sortable list (e.g. built with dragula or a custom drag implementation) as the user drags an item past the visible viewport
  • Kanban-style boards with multiple scrollable columns that all need edge-triggered scrolling during card drags
  • File managers or tree views where dragging an item near the top or bottom of a scrollable pane should reveal more rows
  • Any custom drag-and-drop UI that needs the window itself to scroll when the user drags near the top or bottom of the page

Under The Hood

Architecture The library exports a single AutoScroller constructor (src/index.js, ~345 lines) that closes over all internal state — there are no classes or sub-modules beyond this one file. It attaches a flat set of window-level listeners (mousedown/touchstart/mouseup/touchend/pointerup/mousemove/touchmove/scroll/mouseleave) directly in the constructor, resolves the active target through getTarget/getElementUnderPoint, and drives scrolling via a requestAnimationFrame loop (scrollTick/scrollWindow) that recomputes scroll deltas every frame from element geometry and tracked pointer coordinates. There is no dependency injection or configuration layering; behavior is fully determined by the options object passed once to the constructor, and the watched-elements list is mutated in place by add/remove. Because every helper lives in one flat closure with no separating interface, changing a core assumption (e.g. the scroll-timing model) would touch nearly every function in the file.

Tech Stack Plain ES2015+ JavaScript with no runtime framework, built with Rollup into a CommonJS/UMD-style bundle, an ES-module build, and a minified browser bundle, so it can be consumed via require, import, or a bare <script> tag. It depends on five small, single-purpose sibling packages from the same ecosystem — an animation-frame polyfill, DOM geometry helpers, element-array add/remove helpers, a synthetic mousemove dispatcher, and a loose boolean-coercion helper — each handling one narrow concern rather than the library reimplementing it. Dev tooling is Rollup with buble/commonjs/node-resolve/uglify plugins; a bower.json sits alongside package.json, reflecting the project’s age.

Code Quality There are no automated tests — the test npm script simply prints an error and exits nonzero, and the test/ directory holds only manual HTML demo pages, not a runnable suite. No CI configuration exists in the repo. Error handling is minimal: the code assumes well-formed elements and valid options with no input validation, so malformed input would surface as silent no-ops or runtime exceptions. Naming is clear and the file is consistently formatted, but there is no TypeScript, no type annotations, and no active linter configuration beyond a stale .jshintignore.

What Makes It Unique The one genuinely notable choice is the distance-proportional speed ramp: scroll speed on each axis is computed from exactly how far the pointer sits inside the configurable margin zone, rather than the fixed-rate-past-a-threshold behavior common in comparable snippets — the README calls this out explicitly as the reason v2 feels smoother than v1. Otherwise the overall approach (window-level pointer tracking plus a per-frame animation loop) is the standard pattern for small scrolling utilities, and the library stays deliberately narrow in scope, leaving drag-and-drop and gesture recognition entirely to whatever library it’s paired with.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search