Rendering long lists or grids (hundreds to hundreds of thousands of rows) without janking the browser — only the visible rows are mounted. A zero-dependency TanStack-Virtual alternative.
Overview
Render 100k rows smoothly — headless windowing with fixed or dynamically-measured sizes, overscan and scroll-to-index. useVirtualizer in ~2 KB.
getTotalSize()Total scrollable size for the spacer element.
measureElement(el) / scrollToIndex(i)Dynamic measurement and programmatic scrolling.
Tips
It's headless: you own the markup. Give the scroll container a fixed height + `overflow:auto`, render a spacer of `getTotalSize()`px, and absolutely-position each item from `getVirtualItems()` at `transform: translateY(item.start)`.
For variable row heights, set `data-index={item.index}` and `ref={v.measureElement}` on each row — it measures real heights and corrects the layout.
Tune `overscan` (default 5) to render a few extra rows above/below the viewport for smoother fast-scrolling.
`scrollToIndex(i, { align })` jumps to any row, even one far outside the current window.
Watch out for
The scroll element must actually scroll (a bounded height with `overflow:auto`); if the page itself scrolls instead, offsets won't track.
`estimateSize` should be close to the real size — a wildly wrong estimate makes the scrollbar jump as rows are measured.
Looking for the complete API and more examples? The npm page and GitHub README carry the full reference — or grab the PDF.