Basic Fixed-Height List
Problem
You need to render thousands of list items efficiently. Every row is the same height, so the offset table can be computed once without measuring individual elements.
Solution
The simplest case: every row is the same height. The offset table is built once and never needs rebuilding.
ts
import { createVirtualizer } from '@vielzeug/virtualit';
const data = Array.from({ length: 50_000 }, (_, i) => ({ id: i, label: `Item ${i}` }));
const scrollEl = document.getElementById('scroll')!;
const listEl = document.getElementById('list')!;
const virt = createVirtualizer(scrollEl, {
count: data.length,
estimateSize: 40,
onChange: (virtualItems, totalSize) => {
listEl.style.height = `${totalSize}px`;
listEl.innerHTML = '';
for (const item of virtualItems) {
const el = document.createElement('div');
el.className = 'row';
el.style.cssText = `position:absolute;top:${item.start}px;left:0;right:0;height:40px;line-height:40px;padding:0 12px;`;
el.textContent = data[item.index].label;
listEl.appendChild(el);
}
},
});html
<div id="scroll" style="height:400px;overflow:auto;position:relative;">
<div id="list" style="position:relative;"></div>
</div>Pitfalls
- Calling
createVirtualizerbefore the scroll container is in the DOM gives it a scroll height of 0, disabling virtualization entirely. Always create it insideonMountedorfirstUpdated. - Passing a new options object with a different
countto a secondcreateVirtualizercall creates a fresh instance, losing scroll position. Usevirt.update({ count })for data changes. - Not setting an explicit
heighton the scroll container makes it expand to fit all rendered rows, removing the scroll and disabling virtualization.