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
- default
Props
| Prop | Type | Default | Description |
|---|---|---|---|
items | Item[] | — | The full collection; only the visible window is rendered |
itemHeight | number | — | Fixed row height in px — every row must be this tall |
height | number | — | 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 |
overscan | number | 3 | Extra rows rendered above and below the visible window, to cover fast scrolling. |
ariaLabel | string | — | Accessible label for the list; label it when the list stands alone |
className | string | — | Additional CSS class names merged onto the root element. |
Design tokens
--cascivo-color-accent
When to use
- Lists long enough that rendering every row costs noticeable time or memory (roughly a thousand rows and up)
- Log, result and feed views where the collection is already fully in memory
- Any list whose length is unbounded and rows are a uniform height
When not to use
- Short lists — the machinery costs more than it saves; use List
- Rows of varying height, which this component cannot position without measuring
- Content that must be findable with the browser’s in-page search, which cannot see unrendered rows
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
- List — Plain list when the collection is small enough to render whole
- InfiniteScroll — Loads further pages into the collection this list renders
- DataTable — Columnar data with sorting and selection rather than a flat row list