Usage Guide & Core Concepts
ScrollBooster is designed to be highly configurable. Understanding the engine's internal physics, rendering techniques, and input handlers is crucial for building robust, production-ready interfaces.
The Rendering Pipeline: scrollMode vs. Manual
By design, the ScrollBooster class acts primarily as a mathematical physics engine. It tracks pointer down, move, and up events, calculates velocity, applies friction, and outputs X/Y coordinates.
Automated Rendering (scrollMode)
For convenience, ScrollBooster includes a DOM-manipulation layer controlled by the scrollMode property.
1. scrollMode: 'transform' (The Performance Route)
This is the most common use case for infinite canvases or draggable grids. Under the hood, ScrollBooster applies inline CSS: transform: translate(-x, -y) to your content element.
- Why use it? CSS Transforms trigger hardware (GPU) acceleration. Moving elements via transform bypasses the browser's layout and paint cycles, resulting in silky-smooth 60fps animations, even with complex DOM trees.
- Requirement: The viewport CSS must typically use
overflow: hidden.
2. scrollMode: 'native' (The Accessibility Route)
If your users rely on standard scrollbars, or if you are dealing with massive amounts of text, use the native mode. Here, ScrollBooster updates the viewport's scrollTop and scrollLeft DOM properties directly.
- Why use it? It syncs perfectly with native browser scrollbars and screen readers. Users can still grab the scrollbar, and ScrollBooster's state will update automatically (thanks to internal
scrollevent listeners). - Requirement: The viewport CSS must use
overflow: scrolloroverflow: auto.
Manual Rendering (onUpdate)
If you leave scrollMode undefined, ScrollBooster alters absolutely nothing in the DOM. Instead, it relies on you to intercept the coordinate data via the onUpdate callback.
This is mandatory if you are integrating with libraries like Three.js, Canvas APIs, or declarative UI frameworks (React, Vue) where direct DOM mutation is frowned upon.
new ScrollBooster({
viewport: viewportElement,
// No scrollMode defined
onUpdate: (state) => {
// state.position.x and state.position.y contain the calculated floats.
// Send these to your React state, or update your WebGL camera.
myCustomCamera.position.x = state.position.x;
myCustomCamera.position.y = state.position.y;
}
});
Note on Performance: ScrollBooster internally batches all onUpdate calls using requestAnimationFrame. You do not need to wrap your onUpdate logic in another rAF loop, but you should ensure your logic inside the callback is highly performant.
Tuning the Physics Engine
ScrollBooster achieves a natural feel through two primary physics parameters:
friction(Default:0.05): Determines how quickly the kinetic glide stops after the user releases the pointer.- A value closer to
1(e.g.,0.5) creates a very "sticky" surface where scrolling stops almost instantly. - A value closer to
0(e.g.,0.01) creates an "icy" surface where the content glides for a long time.
- A value closer to
bounceForce(Default:0.1): Determines the elasticity when the content hits the viewport boundaries.- A high value (e.g.,
0.5) causes a harsh, rapid snap-back. - A low value (e.g.,
0.05) causes a soft, lazy rubber-band effect.
- A high value (e.g.,
Handling Complex Inputs & Workflows
Interacting with Forms and Text
Drag-to-scroll inherently conflicts with dragging to highlight text or dragging range sliders. ScrollBooster manages this via two configurations:
inputsFocus(Default:true): Before initiating a drag, ScrollBooster checks the event target. If the user clicked an<input>,<textarea>,<button>,<select>, or<label>, the drag is aborted, allowing native focus and interaction to occur naturally.textSelection(Default:false): If enabled, ScrollBooster runs a computational check (textNodeFromPoint) to see if the user clicked directly on a text node. If true, it permits native text highlighting. Trade-off: This requires DOM traversal on click, which has a slight performance cost.
Emulating Scroll (Wheel & Trackpad)
By default, ScrollBooster only reacts to pointer drag events (mousedown / touchstart). To allow users to navigate the canvas using standard scroll wheels or trackpad swipes, enable emulateScroll: true.
new ScrollBooster({
viewport: viewportElement,
emulateScroll: true,
preventDefaultOnEmulateScroll: 'horizontal'
});
The Trackpad Pitfall: Modern trackpads trigger "back/forward" browser navigation on horizontal swipes. If you are building a horizontal carousel, you must set preventDefaultOnEmulateScroll: 'horizontal' (or 'all'). This intercepts the wheel event, stops the browser from navigating back a page, and pipes the delta exclusively into the ScrollBooster physics engine.
Advanced Flow: shouldScroll
The shouldScroll callback is your ultimate escape hatch. It fires on pointerdown and expects a boolean return value. It allows you to disable dragging based on complex, dynamic business logic.
new ScrollBooster({
viewport: viewport,
shouldScroll: (state, event) => {
// Example: Disable dragging if a specific "Edit Mode" toggle is active in your app
if (window.APP_STATE.isEditMode) return false;
// Example: Disable dragging if clicking on an interactive SVG path
if (event.target.tagName.toLowerCase() === 'path') return false;
return true; // Otherwise, allow drag
}
});
Troubleshooting Pitfalls
Pitfall 1: Dynamic Content Resizing
If you inject new DOM elements, load remote images, or alter CSS that changes the size of your .content element after ScrollBooster has initialized, the physics boundaries will be wrong. The content might stop scrolling too early, or scroll off-screen.
Solution: Call sb.updateMetrics() any time the content dimensions change.
Pitfall 2: Accidental Link Clicks
If a user grabs an <a> tag, drags the canvas, and releases the mouse, the browser will navigate to that link, ruining the UX. ScrollBooster detects this automatically (if the drag offset exceeds 5px) and calls event.preventDefault() natively, but you can also handle it explicitly in the onClick callback if needed. See the Directional Locks & Buttons example for implementation details.