VirtualList

Renders only the rows inside the viewport, so list length costs no extra DOM

Category: display · WCAG 2.2-AA · display, virtual, virtualization, list, performance, scroll

States

Props

PropTypeDefaultDescription
itemsItem[]The full collection; only the visible window is rendered
itemHeightnumberFixed row height in px — every row must be this tall
heightnumberHeight of the scrolling viewport, in px — not a CSS length, because the visible row count is computed from it
renderItem(item: Item, index: number) => React.ReactNodeRenders one row
overscannumber3Extra rows rendered above and below the visible window, to cover fast scrolling.
ariaLabelstringAccessible label for the list; label it when the list stands alone
classNamestringAdditional CSS class names merged onto the root element.

Design tokens

When to use

When not to use

How to build an accessible VirtualList in React →

Examples

Basic

Ten thousand rows cost the same DOM as ten.

<VirtualList
  items={Array.from({ length: 10000 }, (_, i) => i)}
  itemHeight={40}
  height={320}
  ariaLabel="Results"
  renderItem={(n) => <span>Row {n + 1}</span>}
/>

Smoother fast scrolling

A larger overscan trades DOM nodes for fewer blank frames when flinging.

<VirtualList items={rows} itemHeight={40} height={320} overscan={10} renderItem={renderRow} />

Related components

← Back to docs