Skip to content

API

Layout Virtual is split into a framework-agnostic engine and thin framework adapters.

The layout-virtual package contains the core layout classes, DOM renderer, scroll container, event bus, and the vanilla JS/TS component. The React, Vue, and Angular packages wrap the same core layout and renderer contract with framework-specific rendering primitives. That means the virtualization behavior, sizing model, overscan option, CSS class hooks, and event callbacks are intentionally the same across frameworks.

PackageUse
layout-virtualCore engine, public core types, and the vanilla DOM component.
react-layout-virtualReact component wrapper.
vue-layout-virtualVue component wrapper.
angular-layout-virtualAngular component wrapper.

All components render a scrollable container with a viewport and content layer. Items are created from data only for the visible range plus overscan. Item dimensions are measured from real DOM elements, so rows, grids, margins, gaps, and dynamic heights can be handled with normal CSS.

PropTypeDefaultDescription
dataT[]requiredItems to virtualize. Each rendered item receives its original data object and index.
renderItemframework-specificrequired in JS/TS and ReactFunction that renders one item. Vue and Angular use slots/templates instead.
overscanHeightnumber200Extra vertical space, in pixels, rendered outside the visible viewport in the current scroll direction. Higher values reduce blanking during fast scrolling but render more items.
scrollerRefframework-specific element refoptionalExisting scroll element to render into. If omitted, the component creates its own scroller element.
scrollerClassframework-specific class valueoptionalClass applied to the scroll container.
viewportClassframework-specific class valueoptionalClass applied to the viewport element inside the scroller.
contentLayerClassframework-specific class valueoptionalClass applied to the element that contains rendered items.

The current wrappers initialize the virtual list when the component mounts or when the vanilla function is called. Treat data, renderItem, and overscanHeight as initialization inputs in the current API.

Each framework receives the same item payload:

type ListItemProps<T> = {
data: T;
index: number;
};

Assign the index to the data-index attribute of the item root element. This contract allows the library to track rendered elements.

import LayoutVirtual, { type ListItemProps } from 'layout-virtual';
type Item = { title: string };
function renderItem({ data, index }: ListItemProps<Item>) {
const element = document.createElement('article');
element.dataset.index = String(index);
element.textContent = data.title;
return element;
}
const { container } = LayoutVirtual({ data, overscanHeight: 200, renderItem, scrollerClass: 'lv-scroller' });
document.getElementById('app')!.append(container);

The component creates this structure:

<div class="scrollerClass" data-lv-scroller>
<div></div>
<div class="viewportClass" data-lv-viewport>
<div>
<div></div>
<div class="contentLayerClass" data-lv-content-layer>
<!-- rendered items -->
</div>
<div></div>
</div>
</div>
</div>

Use these classes to define the scroller size, overflow behavior, and item layout. For responsive grids, put grid or flex layout styles on contentLayerClass and item styles on the rendered item root.

Layout Virtual also adds stable data attributes to its main DOM layers:

AttributeElementUse
data-lv-scrollerScroll containerSelect the outer scroll element.
data-lv-viewportViewport containerSelect the inner virtual viewport.
data-lv-content-layerContent layerSelect the element that contains rendered items.

These attributes are intended as stable selectors. They can be used for styling, although class props are preferable for normal CSS customization because they keep styling names under application control. They are also useful when you need a direct DOM reference:

const scroller = document.querySelector('[data-lv-scroller]');
const viewport = document.querySelector('[data-lv-viewport]');
const contentLayer = document.querySelector('[data-lv-content-layer]');
EventCallbackDescription
onAfterItemsRendered(startIndex: number, endIndex: number, items: HTMLCollection) => voidFires after the current visible range has been flushed to the DOM. This is the main event for counters, diagnostics, and observing the rendered range.
onChange() => voidInternal event emitted when core data or renderer setup changes.
onResize(width: number, height: number) => voidLow-level scroll container resize event.
onScroll(position: number, direction: 'down' | 'up', scrollDelta: number) => voidLow-level native scroller event.
onContentScroll(position: number, direction: 'down' | 'up', scrollDelta: number) => voidLow-level virtual content scroll event.

onBeforeItemsLoaded and onBeforeItemsUnloaded are present in the event type map, but the current layout does not emit them yet.

FrameworkscrollerRef typeClass prop typeItem renderer
JS / TSHTMLDivElementstringrenderItem(props) => HTMLElement
ReactReact.RefObject<HTMLElement>stringrenderItem(props) => React.ReactNode
VueRef<HTMLElement>Vue ClassValue#renderItem slot
AngularElementRef<HTMLElement>string | string[] | Set<string> | Record<string, boolean>#renderItem template