A high-performance virtualization library for rendering large lists and tables efficiently. Only renders visible items with a custom scrollbar, dramatically reducing DOM nodes and improving performance for datasets with thousands or millions of rows.
- efficient rendering - only renders items currently visible in the viewport
- smooth scrolling - custom scrollbar with optimized scroll handling
- framework agnostic - works with React, vanilla JS, or any framework
- TypeScript support - fully typed APIs
- row reusing - recycles DOM nodes for better garbage collection performance
- lightweight - minimal dependencies
this library is designed to handle extremely large datasets efficiently:
- tested with 500,000+ rows
- only renders ~15-20 DOM nodes regardless of total dataset size
- smooth 60fps scrolling even on 6X CPU slowdown (tested on M1 Macbook Pro)
- minimal memory footprint through DOM node recycling
npm install
npm run devusing the useVirtualScroll hook for a virtualized table:
import { useVirtualScroll } from './hooks/useVirtualScroll';
function VirtualizedTable() {
const ROW_HEIGHT = 40;
const TOTAL_ROWS = 100000;
const VIEWPORT_HEIGHT = 600;
// Initialize virtual scroll
const { scrollbar, virtualizer } = useVirtualScroll({
count: TOTAL_ROWS,
size: ROW_HEIGHT,
viewportSize: VIEWPORT_HEIGHT,
});
const renderedIndices = virtualizer.renderedIndices;
const containerProps = scrollbar.containerProps;
const thumbProps = scrollbar.thumbProps;
return (
<div
{...containerProps}
style={{
...containerProps.style,
height: `${VIEWPORT_HEIGHT}px`,
overflow: 'hidden',
}}
>
<div style={{ position: 'relative' }}>
{renderedIndices.map((rowIdx) => {
const position = rowIdx * ROW_HEIGHT - scrollbar.position;
return (
<div
key={rowIdx}
style={{
position: 'absolute',
height: `${ROW_HEIGHT}px`,
transform: `translateY(${position}px)`,
width: '100%',
}}
>
Row {rowIdx}
</div>
);
})}
</div>
{/* Custom scrollbar thumb */}
<div
{...thumbProps}
style={{
...thumbProps.style,
width: '12px',
background: '#ccc',
borderRadius: '6px',
}}
/>
</div>
);
}interface VirtualScrollOptions {
count: number; // total number of items
size: number; // height of each item in pixels
viewportSize: number; // height of the visible viewport
onChange?: (instance: VirtualScroll) => void; // callback on scroll
}
const virtualScroll = new VirtualScroll(options);properties:
virtualizer.renderedIndices- array of indices currently in viewportvirtualizer.height- total content heightscrollbar.position- current scroll positionscrollbar.containerProps- props to attach to scroll containerscrollbar.thumbProps- props to attach to scrollbar thumb
methods:
updateOptions(options)- update virtualization optionscleanup()- clean up event listeners
const { scrollbar, virtualizer } = useVirtualScroll({
count: number;
size: number;
viewportSize: number;
});the following features are planned for future releases:
- fixed size DOM nodes for GC optimization
- horizontal scrolling & full grid support
- touch events support
- filter/sort/search functionality using workers and sharedArrayBuffer
- dynamic height support
MIT
contributions are welcome! please feel free to submit a pull request.