Choose an API level
Every level uses the same VirtualScroller sizes, offsets, anchoring, and item
measurement. Choose by DOM ownership, not by expected data size.
| Level | Use it when | Framework entry point |
|---|---|---|
| List binding | One viewport contains one virtual block | VirtualList in React, Preact, Solid, and Vue; createVirtualList in Svelte; VirtualController in Lit |
| Layout primitives | The viewport, size element, and rendered range need custom nesting | Framework refs, attachments, composables, or controller refs |
| Direct core | The renderer is canvas, a new adapter, or has no framework lifecycle | VirtualScroller and optionally VirtualScrollerLayout |
Start with the list binding
It owns the three layout bindings and limits framework updates to the rendered range. The canonical implementations are intentionally kept in examples rather than repeated here.
Move down for custom DOM
Use framework layout primitives when content separates the viewport from the virtual size element, or when the page itself scrolls. The required nesting and style ownership do not change; only the framework binding changes.
Read how virtual layout works before changing the tree. Headers and footers may be siblings of the size element, but the rendered-items element remains inside it.
Use a specialized renderer
Semantic tables often need before/after spacer rows instead of an absolutely positioned block. Two-axis grids need independent row and column models. Those renderers still ask core for range and pixel geometry rather than reimplementing virtualization.
Use direct subscriptions only for values the renderer consumes imperatively. The render ownership guide explains which events require framework child reconciliation and which can stay in core-owned DOM updates.