Blog>
Snippets

Customizing Scroll Behavior and Item Sizes in Virtual Lists

Illustrate the process of customizing scroll behavior and handling dynamic item sizes within a virtual list created with TanStack Virtual.
import { useVirtualizer } from '@tanstack/react-virtual';

function VirtualList({ items }) {
  const parentRef = React.useRef();

  const rowVirtualizer = useVirtualizer({
    count: items.length,
    getScrollElement: () => parentRef.current,
    estimateSize: () => 50, // Default size for each item
    overscan: 5,
  });

  return (
    <div ref={parentRef} style={{ overflow: 'auto', height: '100vh' }}>
      <div
        style={{
          height: `${rowVirtualizer.getTotalSize()}px`,
          position: 'relative',
        }}
      >
        {rowVirtualizer.getVirtualItems().map(virtualRow => (
          <div
            key={virtualRow.index}
            style={{
              position: 'absolute',
              top: 0,
              left: 0,
              width: '100%',
              transform: `translateY(${virtualRow.start}px)`,
              height: `${virtualRow.size}px`,
            }}
          >
            {items[virtualRow.index]}
          </div>
        ))}
      </div>
    </div>
  );
}
This code snippet demonstrates setting up a basic virtual list with TanStack Virtual. It initializes a virtualizer for a list, where each item's default size is estimated to be 50px. The virtual list container is a vertically scrollable div that uses absolute positioning for its child elements, positioned according to their virtualized start positions.
rowVirtualizer.measure();
This line of code should be called whenever there's a need to re-measure the size of the items, typically after the data changes or the item's content dynamically adjusts its size. It triggers the re-evaluation of item sizes to ensure the virtual list accurately reflects the variable sizes of its items.
const rowVirtualizer = useVirtualizer({
  count: items.length,
  getScrollElement: () => parentRef.current,
  estimateSize: (index) => calculateDynamicSize(items[index]),
  overscan: 5,
});
This updated initialization for `rowVirtualizer` incorporates a dynamic size calculation for each item in the list. The `estimateSize` function now takes an index and returns the size for that specific item by calling a `calculateDynamicSize` function, which should be implemented to determine each item's size based on its content.