> Leaf UI 0.8.1 · Package: @ifhover/leaf-ui · Source: 435bab23cad7d343653d9b63b049c0b0601eeefb
> Browser documentation: https://ifhover.github.io/leaf-ui/en/components/virtual-list.html

> For AI agents: the complete documentation index is available at https://ifhover.github.io/leaf-ui/en/llms.txt, the full documentation bundle is available at https://ifhover.github.io/leaf-ui/en/llms-full.txt.

# VirtualList

Browse large lists smoothly.

## Basic usage


- Item 1
- Item 2
- Item 3
- Item 4
- Item 5
- Item 6
- Item 7
- Item 8
- Item 9
- Item 10
- Item 11

basic.tsx

Copy code

```tsx lineNumbers file="../../../src/examples/en/virtual-list/basic.tsx"
import { VirtualList } from '@ifhover/leaf-ui';

import { useState } from 'react';

export function VirtualListBasic() {
  const [items] = useState(() =>
    Array.from({ length: 10000 }, (_, index) => ({
      id: String(index),
      name: `Item ${index + 1}`,
    })),
  );
  return (
    <VirtualList
      items={items}
      itemKey={(item) => item.id}
      height={240}
      estimateSize={44}
      renderItem={(item) => <div style={{ padding: '12px 16px' }}>{item.name}</div>}
    />
  );
}
```

Expand code

## More examples


Go to item 501

- **#0**

Content with varying length. 


- **#1**

Content with varying length. Content with varying length. 


- **#2**

Content with varying length. Content with varying length. Content with varying length. 


- **#3**

Content with varying length. 


- **#4**

Content with varying length. Content with varying length. 


- **#5**

Content with varying length. Content with varying length. Content with varying length. 


- **#6**

Content with varying length. 


- **#7**

Content with varying length. Content with varying length. 


- **#8**

Content with varying length. Content with varying length. Content with varying length. 



advanced.tsx

Copy code

```tsx lineNumbers file="../../../src/examples/en/virtual-list/advanced.tsx"
import { Button, Space, VirtualList } from '@ifhover/leaf-ui';

import { useRef, useState } from 'react';

export function VirtualListDynamic() {
  const list = useRef<import('@ifhover/leaf-ui').VirtualListHandle>(null);
  const [items] = useState(() =>
    Array.from({ length: 1000 }, (_, index) => ({
      id: String(index),
      text: 'Content with varying length. '.repeat((index % 3) + 1),
    })),
  );
  return (
    <Space direction="vertical" align="stretch">
      <Button variant="outline" onClick={() => list.current?.scrollToIndex(500, 'start')}>
        Go to item 501
      </Button>
      <VirtualList
        ref={list}
        items={items}
        itemKey={(item) => item.id}
        height={220}
        estimateSize={60}
        renderItem={(item) => (
          <div style={{ padding: 16 }}>
            <strong>#{item.id}</strong>
            <p style={{ margin: '4px 0' }}>{item.text}</p>
          </div>
        )}
      />
    </Space>
  );
}
```

Expand code

## Usage

Keep itemKey stable. estimateSize is used initially; rows are measured afterward. SSR outputs a deterministic initial window that adjusts after mounting.

## Types

Import these types for data, callbacks and refs.

```ts
import type { VirtualListHandle, VirtualListProps } from '@ifhover/leaf-ui';
```

## VirtualListHandle API

| Property         | Type                                                                      | Default  | Description              |
| ---------------- | ------------------------------------------------------------------------- | -------- | ------------------------ |
| `element`        | `HTMLDivElement \| null`                                                  | Required | Scroll container element |
| `scrollToIndex`  | `(index: number, align?: 'auto' \| 'start' \| 'center' \| 'end') => void` | Required | Scroll to an item        |
| `scrollToOffset` | `(offset: number) => void`                                                | Required | Scroll to an offset      |

## VirtualListProps API

| Property       | Type                                             | Default  | Description                                  |
| -------------- | ------------------------------------------------ | -------- | -------------------------------------------- |
| `items`        | `readonly T[]`                                   | Required | Items; keep keys unique and stable           |
| `itemKey`      | `(item: T, index: number) => Key`                | Required | Return a stable identifier                   |
| `renderItem`   | `(item: T, index: number) => ReactNode`          | Required | Custom item renderer                         |
| `height`       | `number`                                         | `320`    | Height, numbers are in pixels                |
| `estimateSize` | `number \| ((item: T, index: number) => number)` | `40`     | Estimated item size; actual size is measured |
| `overscan`     | `number`                                         | `5`      | Items rendered outside the visible range     |
| `emptyContent` | `ReactNode`                                      | —        | Empty list content                           |
| `horizontal`   | `boolean`                                        | `false`  | Horizontal virtual list                      |
