Back to catalog
Component detail entry
Data Display
@vean/ui
SVirtualizer

Virtualizer

Virtualizer belongs to the Data Display category. Start with demos and usage, then use the API tables to finish integration and styling decisions.

Use the quick jump panel to reach overview, usage, demos, and API first, then continue through the full page.

Quick jump

Related components

If you are composing interactions in the same family, these components usually pair well together.

Virtualizer

Overview

A virtual scrolling component that efficiently renders large lists by only rendering items currently in the viewport. SVirtualizer wraps the Aria VirtualizerRoot/VirtualizerContent primitives (built on @tanstack/vue-virtual) — only the visible window of items is mounted into the DOM, keeping large lists fast.

Use a virtualizer for long lists/tables where rendering all rows would be slow. For a listbox/tree with virtual scrolling, see the higher-level integrations (e.g. select, tree).

Usage

Features

  • ⚡ Virtual scrolling — built on @tanstack/vue-virtual; only viewport-visible items render
  • 📊 Data-driven — pass items (any record shape) and estimateSize for row height
  • 📏 Scroll container — height sets the root scroll viewport (with overflow: auto)
  • ↔️ Orientation — options.horizontal renders a horizontally scrolling row
  • 🎚️ TanStack options — pass options (overscan, scrollMargin, paddingStart/End, measurement overrides, …)
  • 🔁 Dynamic mode — dynamic enables variable-height item measurement
  • 🧩 Item slot — the item slot receives { virtualItem, index, item } for custom rendering
  • ♿ Accessible — root is keyboard-scrollable (tabindex="-1") and exposes virtualized content

Component family

  • SVirtualizer (styled) — the entry wrapper; iterates virtualItems into the item slot
  • VirtualizerRoot (Aria) — the scroll container; owns the useVirtualizer instance, computes virtualItems/totalSize/contentStyle
  • VirtualizerContent (Aria) — the sized inner content that positions virtual items
  • VirtualizerItem (Aria) — a positioned virtual item (used by advanced custom builds)

Demos

Basic

Horizontal

Dynamic

API

Aria Layer

5

Virtualizer<T>

8 Props
Props
PropTypeDefaultDescription
contentProps
VirtualizerContentProps
—
Properties forwarded to the content element.
dynamicContentProps
VirtualizerDynamicContentProps
—
Properties forwarded to the dynamic content element.
height
string | number
—
The height of the virtualizer root
items
T[]
—
Items rendered by the component.
options
VirtualizerOptions
—
Options.
dynamic
boolean
—
Whether dynamic.
asChild
boolean
—
Change the default rendered element for the one passed as a child, merging their props and behavior.
as
AsTag | Component
'div'
The element or component this component should render as. Can be overwrite by `asChild`

VirtualizerContent

3 Props
Props
PropTypeDefaultDescription
dynamicContentProps
VirtualizerDynamicContentProps
—
Properties forwarded to the dynamic content element.
asChild
boolean
—
Change the default rendered element for the one passed as a child, merging their props and behavior.
as
AsTag | Component
'div'
The element or component this component should render as. Can be overwrite by `asChild`

VirtualizerDynamicContent

VirtualizerItem

4 Props
Props
PropTypeDefaultDescription
data
VirtualItem
—
Data.
customStyle
boolean
—
Whether custom style.
asChild
boolean
—
Change the default rendered element for the one passed as a child, merging their props and behavior.
as
AsTag | Component
'div'
The element or component this component should render as. Can be overwrite by `asChild`

VirtualizerRoot<T>

6 Props
Props
PropTypeDefaultDescription
height
string | number
—
The height of the virtualizer root
items
T[]
—
Items rendered by the component.
options
VirtualizerOptions
—
Options.
dynamic
boolean
—
Whether dynamic.
asChild
boolean
—
Change the default rendered element for the one passed as a child, merging their props and behavior.
as
AsTag | Component
'div'
The element or component this component should render as. Can be overwrite by `asChild`

Notes

Architecture and benchmark differences

VirtualizerRoot owns the @tanstack/vue-virtual instance and computes virtualItems/totalSize/contentStyle, while SVirtualizer only iterates the virtual items into the item slot. This delegates the measurement/positioning engine to the industry-standard TanStack Virtual (the same engine used by shadcn-ui/TanStack). Ant Design (rc-virtual-list), Element Plus (el-table-v2), Mantine (ListVirtualization) and Naive UI (virtual-list) provide their own virtual engines; VeanUI exposes a thin, engine-agnostic wrapper so any @tanstack/vue-virtual option can flow through.

CapabilityVeanUITanStackAnt DesignElement PlusMantineNaive UI
Virtual engine✅✅✅✅✅✅
Data-driven items✅✅✅✅✅✅
Horizontal mode✅✅✅✅——
Dynamic measurement✅✅————
Full engine options✅✅————

— = unsupported or a different interaction model.

Cautions

  • height sets the root scroll viewport; estimateSize provides the row size used before measurement.
  • items can be any record shape; the item slot receives { virtualItem, index, item }.
  • Pass options (from @tanstack/vue-virtual) for overscan, horizontal, scrollMargin, measurement overrides, etc.
  • dynamic enables variable-height item measurement; otherwise rows are measured once and reused.
  • This is a low-level primitive — for listbox/tree virtual scrolling use the higher-level components that wrap it.

Roadmap

N/A — virtualizer is feature-complete for the current parity set.

FAQ

How do I render a large list?

Pass items, a row estimate-size and a height, with an item slot:

<SVirtualizer :items="rows" :estimate-size="40" :height="400">
  <template #item="{ item }">{{ item.label }}</template>
</SVirtualizer>

How do I scroll horizontally?

Set options.horizontal:

<SVirtualizer :items="cols" :estimate-size="120" :height="300" :options="{ horizontal: true }" />

How do I tune overscan?

Pass overscan in options:

<SVirtualizer :items="rows" :estimate-size="40" :height="400" :options="{ overscan: 10 }" />

How do I support variable-height items?

Set dynamic:

<SVirtualizer :items="rows" dynamic :estimate-size="40" :height="400">
  <template #item="{ item, virtualItem }">{{ item.label }}</template>
</SVirtualizer>

Changelog

Version history is grouped by release so you can quickly see what changed for this component across published versions.

v0.50.0

2026-10-02

Compare release

Style

correct height computation for style binding

Scope: virtualizerAuthors: soybeanjsView commitdb553

Style

correct height computation for style binding

Scope: virtualizerAuthors: soybeanjsView commitdb553

v0.0.2

2025-11-18

Compare release

Feature

implement Virtualizer component with base, dynamic, and horizontal examples

Scope: virtualizerAuthors: soybeanjsView commit02aaa

Feature

implement Virtualizer component with base, dynamic, and horizontal examples

Scope: virtualizerAuthors: soybeanjsView commit02aaa