← All projects

vlist #

PublishedUpdated May 2, 2026

High-performance virtual list engine for the web. Framework-agnostic core with first-class bindings for React, Vue, Solid, and Svelte.

Why vlist? #

Virtual list libraries have been around for years, but almost all of them are locked to a single framework. react-window, react-virtuoso, TanStack Virtual, Legend List — they all assume you're inside React.

vlist takes a different approach: vanilla first, framework optional.

Library Framework Dependencies Gzipped Tree-shakeable
react-window React 1 ~6 KB No
react-virtuoso React 1 ~16 KB No
TanStack Virtual Multi (React-dominant) 1+ ~10 KB Partial
Legend List v3 React / RN 1+ ~21 KB No
vlist None 0 8.7 KB Yes

Zero runtime dependencies means no supply chain risk, no version conflicts, no transitive node_modules bloat. The entire library is built from scratch in TypeScript.

Constant Memory #

Most virtual list libraries create internal data structures that grow linearly with your dataset. vlist doesn't.

Dataset size vlist memory
10,000 items ~0.2 MB
100,000 items ~0.2 MB
1,000,000 items ~0.4 MB

With 100,000 items in your dataset, roughly 26 DOM elements exist at any given time. The scroll handler runs at 120 FPS with zero allocations on the hot path.

Pay Only for What You Use #

vlist uses a builder pattern with opt-in features. The base is 8.7 KB gzipped. Each feature adds only what it needs:

Configuration Gzipped Features
Base only 10.3 KB None
+ Selection 12.1 KB withSelection()
+ Grid 14.3 KB withGrid() + withScrollbar()
+ Groups 14.6 KB withGroups()
+ Async 14.6 KB withAsync() + withPage()
+ Scale 12.9 KB withScale() + withScrollbar()
All features ~33 KB Everything

Compare this to monolithic libraries where you ship every feature whether you use it or not.

Features #

Every feature is self-contained and tree-shakeable:

Feature How
Lists (vertical & horizontal) Built-in
Grids withGrid()
Masonry withMasonry()
Data tables withTable()
Drag-and-drop reordering withSortable()
Grouped sections with sticky headers withGroups()
Async/infinite loading withAsync()
Multi-selection withSelection()
1M+ items with scroll compression withScale()
Auto-measure items withAutoSize()
Page-level scrolling withPage()
Scroll save/restore withSnapshots()
Custom scrollbar withScrollbar()
Reverse mode (chat UIs) reverse: true
Keyboard navigation & ARIA Built-in

Quick Start #

npm install vlist
import { vlist } from 'vlist';
import 'vlist/styles';

const list = vlist({
  container: '#list',
  items: data,
  item: {
    height: 48,
    template: (item) => `<div class="row">${item.name}</div>`,
  },
}).build();

That's a working virtual list. Thousands of items, only ~20 DOM nodes.

Framework Adapters #

vlist ships adapters for React, Vue, Svelte, and SolidJS. They're thin wrappers — a few lines of glue code that translate framework idioms (refs, hooks, reactivity) into vlist's vanilla API. The core never imports React, never calls useState, never touches a virtual DOM.

If your framework doesn't have an adapter yet, you can integrate vlist in an afternoon. It's just DOM.