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
itemHeightnumber—Fixed row height in px — every row must be this tall
heightnumber—Height 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.ReactNode—Renders one row
overscannumber3Extra rows rendered above and below the visible window, to cover fast scrolling.
labelstring—Alias of `ariaLabel` — the same invisible accessible name under the other spelling. Neither is deprecated.
ariaLabelstring—Accessible label for the list; label it when the list stands alone
classNamestring—Additional 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