Virtual
@domphy/virtual renders only the rows/columns currently in view — essential for long lists, grids, and tables — with dynamic measurement, overscan, sticky ranges, and smooth scroll-to.
It is a 1-1 port of @tanstack/virtual-core v3.17.0 (MIT, © Tanner Linsley and the TanStack team). The src/ is byte-identical to upstream, so the entire TanStack Virtual reference applies as-is and future versions can be diffed and merged directly. The only addition is the Domphy adapter in src/domphy/.
The core is framework-agnostic with zero dependencies.
Install
npm install @domphy/virtual @domphy/core
@domphy/core is a peer dependency of the adapter only.
Live Example
10,000 rows; only the visible ones are mounted.
Adapter
createVirtualizer(options) (from @domphy/virtual/domphy) owns the scroll element and binds the virtualizer to Domphy reactivity.
import { createVirtualizer } from "@domphy/virtual/domphy"
const list = createVirtualizer<HTMLDivElement, HTMLDivElement>({
count: rows.length,
estimateSize: () => 32,
overscan: 10,
})
| Member | Description |
|---|---|
getVirtualItems(l) | Reactive list of visible VirtualItems — read with the listener inside the items function. |
getTotalSize(l) | Reactive total scroll size, for the spacer height/width. |
setScrollElement(el) | Wire the scroll container DOM node; call from its _onMount. |
measureElement(el) | Dynamic measurement ref; call from each item's _onMount for variable sizes. |
scrollToIndex(i, opts?) / scrollToOffset(px, opts?) | Imperative scrolling. |
setOptions(opts) | Update count/options, then re-measure. |
virtualizer | The underlying Virtualizer — the full virtual-core API. |
version(l) | Raw reactive change counter. |
destroy() | Detach observers; call from _onRemove. |
Wiring
- Make the outer element a fixed-height scroll container and wire it:
_onMount: (node) => list.setScrollElement(node.domElement). - Inside, render a relative spacer whose height is
list.getTotalSize(l). - Map
list.getVirtualItems(l)into absolutely-positioned children using each item'sstart/size, keyed byitem.key. - For variable-height rows, call
list.measureElement(node.domElement)from each row's_onMountand drop the fixedheight.
Pass your own observeElementRect / observeElementOffset / scrollToFn to virtualize against the window instead of an element.