Virtual List Rendering
Virtualized list rendering technique: only mount DOM nodes for visible rows plus a small overscan buffer, using scrollTop, itemHeight, and containerHeight to compute the visible window.…
$ prime install @community/pattern-virtual-list-rendering Projection
Always in _index.xml · the agent never has to ask for this.
VirtualListRendering [pattern] v1.0.0
Virtualized list rendering technique: only mount DOM nodes for visible rows plus a small overscan buffer, using scrollTop, itemHeight, and containerHeight to compute the visible window. Recommended libraries: @tanstack/react-virtual (lightweight) or react-window for fixed-size lists.
Loaded when retrieval picks the atom as adjacent / supporting.
VirtualListRendering [pattern] v1.0.0
Virtualized list rendering technique: only mount DOM nodes for visible rows plus a small overscan buffer, using scrollTop, itemHeight, and containerHeight to compute the visible window. Recommended libraries: @tanstack/react-virtual (lightweight) or react-window for fixed-size lists.
Problem
Rendering a list of 1000+ items as DOM nodes creates O(n) memory usage, causes slow initial render, and produces janky scroll above ~200-500 items depending on node complexity.
Solution
Maintain a virtual DOM window: calculate visibleStart and visibleEnd from scrollTop/itemHeight, render only those items plus a buffer (8-10 rows), and pad the container with a spacer div at the correct total height so scroll position is correct.
Code
// Manual virtualization calculation
function getVisibleRange(scrollTop, containerHeight, itemHeight, itemCount, overscan = 8) {
const visibleStart = Math.floor(scrollTop / itemHeight);
const visibleEnd = Math.ceil((scrollTop + containerHeight) / itemHeight);
return {
start: Math.max(0, visibleStart - overscan),
end: Math.min(itemCount - 1, visibleEnd + overscan),
};
}
// Container structure
<div class="viewport" style="height: 600px; overflow-y: auto" onscroll={handleScroll}>
{/* Spacer at full list height — maintains correct scrollbar size */}
<div style={{ height: totalHeight, position: 'relative' }}>
{visibleItems.map((item, i) => (
<div key={item.id}
style={{ position: 'absolute', top: (startIndex + i) * ITEM_HEIGHT, height: ITEM_HEIGHT }}>
{renderItem(item)}
</div>
))}
</div>
</div>
// @tanstack/react-virtual (recommended over manual implementation)
import { useVirtualizer } from '@tanstack/react-virtual';
const virtualizer = useVirtualizer({
count: items.length, getScrollElement: () => parentRef.current,
estimateSize: () => 48, overscan: 8,
});
Use When
- Rendering a list or table with more than ~200 items
- Performance profiling shows slow list scroll or high DOM node count
- Real-time data streams that continuously append rows (logs, feeds)
Libraries
- @tanstack/react-virtual — zero-dependency, supports variable height, most flexible
- react-window — fixed or variable height, widely used, lighter API
- Custom implementation — appropriate only for fixed-height items with simple DOM
Loaded when retrieval picks the atom as a focal / direct hit.
VirtualListRendering [pattern] v1.0.0
Virtualized list rendering technique: only mount DOM nodes for visible rows plus a small overscan buffer, using scrollTop, itemHeight, and containerHeight to compute the visible window. Recommended libraries: @tanstack/react-virtual (lightweight) or react-window for fixed-size lists.
Problem
Rendering a list of 1000+ items as DOM nodes creates O(n) memory usage, causes slow initial render, and produces janky scroll above ~200-500 items depending on node complexity.
Solution
Maintain a virtual DOM window: calculate visibleStart and visibleEnd from scrollTop/itemHeight, render only those items plus a buffer (8-10 rows), and pad the container with a spacer div at the correct total height so scroll position is correct.
Code
// Manual virtualization calculation
function getVisibleRange(scrollTop, containerHeight, itemHeight, itemCount, overscan = 8) {
const visibleStart = Math.floor(scrollTop / itemHeight);
const visibleEnd = Math.ceil((scrollTop + containerHeight) / itemHeight);
return {
start: Math.max(0, visibleStart - overscan),
end: Math.min(itemCount - 1, visibleEnd + overscan),
};
}
// Container structure
<div class="viewport" style="height: 600px; overflow-y: auto" onscroll={handleScroll}>
{/* Spacer at full list height — maintains correct scrollbar size */}
<div style={{ height: totalHeight, position: 'relative' }}>
{visibleItems.map((item, i) => (
<div key={item.id}
style={{ position: 'absolute', top: (startIndex + i) * ITEM_HEIGHT, height: ITEM_HEIGHT }}>
{renderItem(item)}
</div>
))}
</div>
</div>
// @tanstack/react-virtual (recommended over manual implementation)
import { useVirtualizer } from '@tanstack/react-virtual';
const virtualizer = useVirtualizer({
count: items.length, getScrollElement: () => parentRef.current,
estimateSize: () => 48, overscan: 8,
});
Use When
- Rendering a list or table with more than ~200 items
- Performance profiling shows slow list scroll or high DOM node count
- Real-time data streams that continuously append rows (logs, feeds)
Libraries
- @tanstack/react-virtual — zero-dependency, supports variable height, most flexible
- react-window — fixed or variable height, widely used, lighter API
- Custom implementation — appropriate only for fixed-height items with simple DOM
Problem
Rendering a list of 1000+ items as DOM nodes creates O(n) memory usage, causes slow initial render, and produces janky scroll above ~200-500 items depending on node complexity.
Solution
Maintain a virtual DOM window: calculate visibleStart and visibleEnd from scrollTop/itemHeight, render only those items plus a buffer (8-10 rows), and pad the container with a spacer div at the correct total height so scroll position is correct.
Code
// Manual virtualization calculation
function getVisibleRange(scrollTop, containerHeight, itemHeight, itemCount, overscan = 8) {
const visibleStart = Math.floor(scrollTop / itemHeight);
const visibleEnd = Math.ceil((scrollTop + containerHeight) / itemHeight);
return {
start: Math.max(0, visibleStart - overscan),
end: Math.min(itemCount - 1, visibleEnd + overscan),
};
}
// Container structure
<div class="viewport" style="height: 600px; overflow-y: auto" onscroll={handleScroll}>
{/* Spacer at full list height — maintains correct scrollbar size */}
<div style={{ height: totalHeight, position: 'relative' }}>
{visibleItems.map((item, i) => (
<div key={item.id}
style={{ position: 'absolute', top: (startIndex + i) * ITEM_HEIGHT, height: ITEM_HEIGHT }}>
{renderItem(item)}
</div>
))}
</div>
</div>
// @tanstack/react-virtual (recommended over manual implementation)
import { useVirtualizer } from '@tanstack/react-virtual';
const virtualizer = useVirtualizer({
count: items.length, getScrollElement: () => parentRef.current,
estimateSize: () => 48, overscan: 8,
});
Use When
- Rendering a list or table with more than ~200 items
- Performance profiling shows slow list scroll or high DOM node count
- Real-time data streams that continuously append rows (logs, feeds)
Libraries
- @tanstack/react-virtual — zero-dependency, supports variable height, most flexible
- react-window — fixed or variable height, widely used, lighter API
- Custom implementation — appropriate only for fixed-height items with simple DOM
Source
prime-system/examples/frontend-design/primes/compiled/@community/pattern-virtual-list-rendering/atom.yaml