VVirtualList renders only the rows near its viewport, for lists too long to render whole. It is its own scroll container: give it a height, or a bounded height in your own CSS.
itemSize is only the height assumed for rows not rendered yet. Each row is measured once and remembered under its itemKey; set it when rows can be inserted, removed or reordered.
vue
Note 1
Paid in three instalments after a dispute about the delivery date, settled with a discount on the next order.
Note 2
Paid on delivery.
Note 3
Paid on delivery.
Note 4
Paid in three instalments after a dispute about the delivery date, settled with a discount on the next order.
Note 5
Paid on delivery.
Note 6
Paid on delivery.
Note 7
Paid in three instalments after a dispute about the delivery date, settled with a discount on the next order.
Note 8
Paid on delivery.
Note 9
Paid on delivery.
Note 10
Paid in three instalments after a dispute about the delivery date, settled with a discount on the next order.
<script setup lang="ts">
import { VVirtualList } from 'vectis-ui'
const notes = Array.from({ length: 2000 }, (_, i) => ({
id: i + 1,
text:
i % 3 === 0
? 'Paid in three instalments after a dispute about the delivery date, settled with a discount on the next order.'
: 'Paid on delivery.',
}))
</script>
<template>
<VVirtualList
:items="notes"
item-key="id"
:item-size="64"
:height="320"
label="Notes"
class="list"
>
<template #default="{ item }">
<article class="note">
<strong>Note {{ item.id }}</strong>
<p>{{ item.text }}</p>
</article>
</template>
</VVirtualList>
</template>
<style scoped>
.list {
max-inline-size: 360px;
border: 1px solid var(--vectis-color-border);
}
.note {
padding: var(--vectis-space-2) var(--vectis-space-3);
border-block-end: 1px solid var(--vectis-color-border);
}
.note p {
margin: var(--vectis-space-1) 0 0;
color: var(--vectis-color-text-muted);
}
</style>
Scrolling to a row
The scrollToIndex(index, align) method renders the row if needed and brings it into view: at the start, center or end, or with the smallest movement by default.
The list has the list role and takes the focus, so the keyboard scrolls it. The row holding the focus stays rendered while the list scrolls away. When every row holds a control, tabindex="-1" removes the list’s own tab stop. Find-in-page only reaches rendered rows: offer a search for long lists.