Rooks
HooksExperimental Hooks

useScroll

Track an element's scroll offsets and scrollable bounds.

About

Track scroll position, viewport size, and total scrollable size for a single element using a callback ref.

Example

import { useScroll } from "rooks/experimental";

function Example() {
  const [ref, scroll] = useScroll();

  return (
    <div>
      <div ref={ref} style={{ height: 120, overflow: "auto" }}>
        <div style={{ height: 400 }}>Scrollable content</div>
      </div>
      <p>Top: {scroll.scrollTop}</p>
    </div>
  );
}

Parameters

OptionTypeDefaultDescription
throttleMsnumber0Minimum time between measurements; non-positive values disable throttling.
disabledbooleanfalseDetach observers/listeners and reset all measurements to zero.
onScroll(state: ScrollState) => voidundefinedRuns after a changed measurement is committed.

Return value

Returns [ref, scrollState]. Attach the callback ref to one HTMLElement. scrollState contains scrollLeft, scrollTop, clientWidth, clientHeight, scrollWidth, and scrollHeight, all initially 0.

Behavior and lifecycle

The hook measures immediately, after passive scroll events, and after container or descendant resize, subtree mutation, captured resource loads, or font loading completes. Throttling performs a leading measurement and at most one trailing measurement. Changing the element or options removes the listeners, disconnects observers, and clears a pending timer; unmount does the same.

Compatibility and accessibility

SSR and a missing element return zeroes. Without ResizeObserver or MutationObserver, scrolling still updates the state, but non-scroll size/content changes may not. Give custom scroll regions an accessible name and keyboard focus only when that improves navigation; do not hide essential content solely because it is outside the current measurements.

On this page