Blog>
Snippets

Creating a Virtualized Grid with Dynamic Sizes

Showcase the setup of a virtualized grid layout where each cell has dynamic content size, using TanStack Virtual's dynamic size features.
import { useVirtual } from '@tanstack/react-virtual';
import { useRef } from 'react';
Import the necessary hooks from React and the useVirtual hook from '@tanstack/react-virtual'.
const parentRef = useRef(null);
Create a ref for the grid parent container to track its scroll.
const rowVirtualizer = useVirtual({
  size: 100, // Number of rows in the grid
  parentRef,
  estimateSize: () => 35, // Initial estimated row height
  overscan: 5, // How many items to render outside of the visible area
});
Instantiate a row virtualizer with an estimated size for dynamic row heights. The `size` property defines the total count of items.
const columnVirtualizer = useVirtual({
  horizontal: true,
  size: 100, // Number of columns in the grid
  parentRef,
  estimateSize: () => 100, // Initial estimated column width
  overscan: 5, // How many items to render outside of the visible area
});
Instantiate a column virtualizer for a grid that has dynamic column widths. Setting `horizontal` to true enables horizontal virtualization.
const gridStyle = {
  height: `100vh`,
  width: `100%`,
  overflow: 'auto',
  position: 'relative',
};
Define the style for the grid container, which includes setting its position to relative to position the virtualized items absolutely within it.
const renderVirtualGrid = () => (
  <div ref={parentRef} style={gridStyle}>
    <div style={{
      height: `${rowVirtualizer.totalSize}px`,
      width: `${columnVirtualizer.totalSize}px`,
      position: 'relative',
    }}>
      {rowVirtualizer.virtualItems.map(rowVirtual => (
        columnVirtualizer.virtualItems.map(columnVirtual => (
          <div key={`${rowVirtual.index}-${columnVirtual.index}`} style={{
            position: 'absolute',
            top: `${rowVirtual.start}px`,
            left: `${columnVirtual.start}px`,
            height: `${rowVirtual.size}px`,
            width: `${columnVirtual.size}px`,
          }}>
            {/* Render your content based on rowVirtual.index and columnVirtual.index */}
            Item {rowVirtual.index}-{columnVirtual.index}
          </div>
        ))
      ))}
    </div>
  </div>
);
This function renders the virtualized grid. Each cell of the grid is positioned absolutely within the parent based on its virtual position and size.