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.
Packages
Section titled “Packages”| Package | Use |
|---|---|
layout-virtual | Core engine, public core types, and the vanilla DOM component. |
react-layout-virtual | React component wrapper. |
vue-layout-virtual | Vue component wrapper. |
angular-layout-virtual | Angular component wrapper. |
Component API
Section titled “Component API”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.
| Prop | Type | Default | Description |
|---|---|---|---|
data | T[] | required | Items to virtualize. Each rendered item receives its original data object and index. |
renderItem | framework-specific | required in JS/TS and React | Function that renders one item. Vue and Angular use slots/templates instead. |
overscanHeight | number | 200 | Extra 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. |
scrollerRef | framework-specific element ref | optional | Existing scroll element to render into. If omitted, the component creates its own scroller element. |
scrollerClass | framework-specific class value | optional | Class applied to the scroll container. |
viewportClass | framework-specific class value | optional | Class applied to the viewport element inside the scroller. |
contentLayerClass | framework-specific class value | optional | Class 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.
Item Rendering
Section titled “Item Rendering”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);import LayoutVirtual, { type ListItemProps } from 'react-layout-virtual';
type Item = { title: string };
function Article({ data, index }: ListItemProps<Item>) { return ( <article data-index={index}> {data.title} </article> );}
<LayoutVirtual<Item> data={data} overscanHeight={200} renderItem={Article} scrollerClass="lv-scroller" />;<script setup lang="ts">import LayoutVirtual from 'vue-layout-virtual';
type Item = { title: string };</script>
<template> <layout-virtual :data="data" :overscan-height="200" scroller-class="lv-scroller"> <template #renderItem="{ data: item, index }"> <article :data-index="index"> {{ item.title }} </article> </template> </layout-virtual></template>import LayoutVirtual from 'angular-layout-virtual';
type Item = { title: string };
@Component({ standalone: true, imports: [LayoutVirtual], template: ` <layout-virtual [data]="data" [overscanHeight]="200" scrollerClass="lv-scroller" > <ng-template #renderItem let-data="data" let-index="index"> <article [attr.data-index]="index"> {{ data.title }} </article> </ng-template> </layout-virtual> `,})Class Hooks
Section titled “Class Hooks”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.
Data Attributes
Section titled “Data Attributes”Layout Virtual also adds stable data attributes to its main DOM layers:
| Attribute | Element | Use |
|---|---|---|
data-lv-scroller | Scroll container | Select the outer scroll element. |
data-lv-viewport | Viewport container | Select the inner virtual viewport. |
data-lv-content-layer | Content layer | Select 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]');Events
Section titled “Events”| Event | Callback | Description |
|---|---|---|
onAfterItemsRendered | (startIndex: number, endIndex: number, items: HTMLCollection) => void | Fires 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 | () => void | Internal event emitted when core data or renderer setup changes. |
onResize | (width: number, height: number) => void | Low-level scroll container resize event. |
onScroll | (position: number, direction: 'down' | 'up', scrollDelta: number) => void | Low-level native scroller event. |
onContentScroll | (position: number, direction: 'down' | 'up', scrollDelta: number) => void | Low-level virtual content scroll event. |
onBeforeItemsLoaded and onBeforeItemsUnloaded are present in the event type map, but the current layout does not emit them yet.
Framework Type Notes
Section titled “Framework Type Notes”| Framework | scrollerRef type | Class prop type | Item renderer |
|---|---|---|---|
| JS / TS | HTMLDivElement | string | renderItem(props) => HTMLElement |
| React | React.RefObject<HTMLElement> | string | renderItem(props) => React.ReactNode |
| Vue | Ref<HTMLElement> | Vue ClassValue | #renderItem slot |
| Angular | ElementRef<HTMLElement> | string | string[] | Set<string> | Record<string, boolean> | #renderItem template |