All questions

Virtual Scroll List

Premium

Virtual Scroll List

Render 100,000 rows into the DOM and the browser chokes — layout, paint, and memory all blow up. Virtual scrolling (windowing) fixes it: only the ~20 rows actually on screen exist as DOM nodes. The trick is faking the rest — give the scroll container the full height so the scrollbar is honest, then translate the handful of real rows to the right place as the user scrolls. This is the engine inside react-window, TanStack Virtual, and every performant infinite feed.

Implement virtualScrollList(options) — the pure math that, given the scroll position and row metrics, returns which rows to render and where. No DOM needed.

Signature

function virtualScrollList({ itemCount, itemHeight, viewportHeight, scrollTop, overscan }) {
  return { startIndex, endIndex, items, totalHeight, offsetTop, visibleCount };
}

Examples

// 1000 rows of 50px, a 500px viewport, scrolled 500px down
virtualScrollList({ itemCount: 1000, itemHeight: 50, viewportHeight: 500, scrollTop: 500 });
// { startIndex: 10, endIndex: 19, offsetTop: 500, totalHeight: 50000, visibleCount: 10, items: [...] }
// overscan renders a few extra rows above/below to hide fast-scroll gaps
virtualScrollList({ itemCount: 1000, itemHeight: 50, viewportHeight: 500, scrollTop: 500, overscan: 3 });
// startIndex 7, endIndex 22

Notes

  • Direct math, not iterationstartIndex = floor(scrollTop / itemHeight), count = ceil(viewportHeight / itemHeight) (plus a partial row). Never loop over all itemCount rows.
  • totalHeight sizes the containeritemCount * itemHeight, so the scrollbar reflects the full list; offsetTop (startIndex * itemHeight) positions the rendered window.
  • Overscan — render overscan extra rows on each side (clamped to [0, itemCount-1]) so a fast scroll doesn't flash blank.
  • Clamp — bound scrollTop to [0, totalHeight - viewportHeight]; an empty list renders nothing (endIndex -1).

Unlock the solution & editor

  • Runnable editor + tests

    Solve in the browser with instant Jest feedback.

  • Detailed solutions

    Walkthroughs, edge cases, and complexity notes.

  • Multi-framework variants

    React, Vue, Vanilla, Angular — same question, different stacks.

Upgrade to Premium