createVirtual
Virtual scrolling composable for efficiently rendering large lists by only rendering visible items.
Usage
The createVirtual composable efficiently renders large lists by only mounting visible items plus a small overscan buffer. Pass an array of items and configure the item height to get back sliced items, scroll handlers, and positioning values.
<script setup lang="ts">
import { createVirtual } from '@vuetify/v0'
import { shallowRef } from 'vue'
const items = shallowRef(
Array.from({ length: 10_000 }, (_, i) => `Item ${i + 1}`)
)
const { element, items: visible, offset, size, scroll, scrollTo } = createVirtual(items, {
itemHeight: 40,
})
</script>
<template>
<div ref="element" class="h-[300px] overflow-y-auto" @scroll="scroll">
<div :style="{ height: `${offset}px` }" />
<div v-for="item in visible" :key="item.index">
{{ item.raw }}
</div>
<div :style="{ height: `${size}px` }" />
</div>
</template>Context / DI
Use createVirtualContext to share a virtual scroll instance across a component tree:
import { createVirtualContext } from '@vuetify/v0'
import { shallowRef } from 'vue'
const items = shallowRef([...])
export const [useVirtual, provideVirtual, virtual] =
createVirtualContext(items, {
namespace: 'my:virtual',
itemHeight: 40,
})
// In parent component
provideVirtual()
// In child component
const { items: visible, offset, size, scroll } = useVirtual()Architecture
The rendering pipeline transforms scroll events into visible item ranges:
Reactivity
| Property/Method | Reactive | Notes |
|---|---|---|
element | Ref, assign scroll container | |
items | Computed, visible items with index | |
offset | ShallowRef, readonly (top spacer height) | |
size | ShallowRef, readonly (bottom spacer height) | |
state | ShallowRef ('loading' | 'empty' | 'error' | 'ok') | |
scroll() | Call on @scroll; schedules a visible-range update via rAF | |
scrollend() | Call on @scrollend; alias of scroll() | |
scrollTo(index, options?) | Scroll to item by index; accepts behavior, block, offset | |
resize(index, height) | Notify of a dynamic item height change; triggers offset rebuild | |
reset() | Reset state to 'ok' and restore scroll anchor |
Source items The items ref passed to createVirtual() is watched for changes. When items change, the virtual scroller updates automatically.
Examples
A 10,000-row employee directory — only the visible window is mounted to the DOM.
FAQ
offset sizes a top spacer and size sizes a bottom spacer. Together they keep the native scrollbar proportional to the full list while only the visible window of rows is actually mounted.
Configure a base itemHeight, then call resize(index, height) after each row measures itself. That notifies the scroller of the new height and triggers an offset rebuild.
createVirtual windows whatever array you pass, so filter or sort first and feed the result in — pair it with createFilter, or use createDataTable’s VirtualDataTableAdapter to hand table.items to the scroller. The source ref is watched, so the window reflows when the list changes.
Call scrollTo(index, options?) — it accepts behavior, block, and offset, so scrollTo(500, { behavior: 'smooth' }) brings item 500 into view. Bound the index with clamp so it can’t point past the data.
Benchmarks
Every operation is profiled across multiple dataset sizes to measure real-world throughput. Each benchmark is assigned a performance tier—good, fast, blazing, or slow—and groups are scored by averaging their individual results so you can spot bottlenecks at a glance. This transparency helps you make informed decisions about which patterns scale for your use case. Learn more in the benchmarks guide.