Skip to Content
⭐️ Leave a star →
ComponentsVirtualizer

Virtualizer

A windowing primitive: renders only the items in view (plus overscan), measuring real item sizes as they appear. Supply a count and a render function for a single item — the Virtualizer handles scrolling, positioning, and measurement. Supports vertical and horizontal axes.

Features

Renders only visible items plus overscan — handles lists of tens of thousands of rows.
Measures real item sizes via ResizeObserver; estimateSize is used until measured.
Vertical or horizontal scroll axis.
Render-prop / scoped slot receives each VirtualItem (index, start, size).
Stable keys via getItemKey for reordering lists.

Example

Items

1,000
0Item number 0
1Item number 1
2Item number 2
3Item number 3
import { Virtualizer } from '@wire-ui/react' <Virtualizer.Root count={1000} estimateSize={44}> {({ index }) => <div>Item number {index}</div>} </Virtualizer.Root>

Sizing

Virtualizer.Root is itself the scroll container, so give it a fixed extent along the scroll axis (e.g. h-80 for vertical, a fixed h-* with width for horizontal). It applies position: relative and the appropriate overflow automatically. Each item is absolutely positioned at its computed offset.

estimateSize is the assumed item size (px) before measurement. Real sizes are measured via ResizeObserver once items render, so variable-height content settles into place — set estimateSize close to the average for the best initial scrollbar.

Horizontal

Set orientation="horizontal" to scroll along the x-axis. estimateSize then refers to item width, and items should fill the container height.

<Virtualizer.Root count={5000} estimateSize={120} orientation="horizontal" className="h-32 w-full"> {({ index }) => <div className="h-full w-[120px]">#{index}</div>} </Virtualizer.Root>

Using data attributes

Virtualizer.Root sets data-orientation on the scroll container. The internal sizer carries data-virtualizer-sizer and each rendered item carries data-virtual-item and data-index.

[data-orientation="vertical"] { /* vertical scroll */ } [data-orientation="horizontal"] { /* horizontal scroll */ }

Root props

PropTypeDefaultDescription
countnumberrequiredTotal number of items.
estimateSizenumber50Estimated item size (px) before measurement.
overscannumber4Extra items rendered beyond the viewport on each side.
orientation'vertical' | 'horizontal''vertical'Scroll axis.
getItemKey(index: number) => KeyStable key per index (helps when the list reorders). Defaults to the index.
children(item: VirtualItem) => ReactNoderequiredRender a single item. In Vue this is a scoped slot.

VirtualItem

The render function (React/Solid) or scoped slot (Vue) receives a VirtualItem per visible row. In Vue the slot props are spread as item, index, start, and size.

FieldTypeDescription
indexnumberIndex of the item in the full list.
startnumberOffset from the start of the list along the scroll axis, in px.
sizenumberMeasured (or estimated) size along the scroll axis, in px.

Data attributes

AttributeElementValues
data-orientationRoot"vertical" / "horizontal"
data-virtualizer-sizerSizerPresent on the inner spacer element
data-virtual-itemItemPresent on each rendered item
data-indexItemThe item’s index

Accessibility

  • The Virtualizer is a layout primitive and applies no ARIA roles itself — wrap or compose it with semantic markup (e.g. a list, Chat.List) appropriate to your content.
  • Because off-screen items are not in the DOM, ensure any keyboard or screen-reader navigation accounts for virtualized content (e.g. drive scrolling programmatically to bring a target item into view).
Last updated on

MIT License © 2026 wire-ui

Virtualizer – Wire UI