Virtual Scroll Comparison

@pdanpdan/virtual-scroll and seven other Vue 3 virtualization libraries. Versions, publish dates, star counts and bundle sizes were checked on 2026-10-29. This package's row is measured from its build on every docs build.

This page compares the Vue 3 packages that virtualize lists and grids: which features each one includes, what an entry costs in bytes, and how the APIs differ. The feature matrix is the only place where a support level is stated.

The table covers this package, vue-virtual-scroller, @tanstack/vue-virtual, virtua, vueuc, vue-virtual-scroll-list, @ceriousdevtech/vue-cerious-scroll and vlist.

The Contenders

PackageLatestPublishedGitHub starsMin / gzipFeature scoreAPI style
@pdanpdan/virtual-scroll2.3.02026-10-291380.3 / 23.4 kB47 / 51 (92%)Component + composables + extensions, plus a lean /core entry
↳ /core component62.0 / 18.0 kB35 / 51 (69%)
↳ headless composable34.1 / 10.9 kB19 / 51 (37%)Engine only - the observers, extensions and keyboard/scrollbar composables are separate imports
↳ headless + observers, keyboard, scrollbar42.5 / 13.8 kB25 / 51 (49%)Engine + the measurement, keyboard and scrollbar composables
vue-virtual-scroller3.0.52026-08-1210,79529.0 / 10.4 kB15.5 / 51 (30%)Components (Scroller, RecycleScroller, DynamicScroller, TableScroller)
@tanstack/vue-virtual3.13.502026-10-297,177 (monorepo)33.1 / 9.9 kB27 / 51 (53%)Headless composable (useVirtualizer)
virtua0.54.02026-10-273,7559.8 / 4.7 kB29.5 / 51 (58%)Components (VList, VGrid, VMasonry) + handle
vueuc0.4.662026-08-1930922.9 / 8.6 kB9 / 51 (18%)Component (VVirtualList)
vue-virtual-scroll-list2.3.52023-05-294,49515.3 / 4.9 kB10 / 51 (20%)Component
vlist (+ vlist/vue)3.3.02026-10-201839.2 / 12.9 kB36.5 / 51 (72%)Vanilla core (createVList) + framework entries (vlist/vue), plugins passed per feature
↳ vlist/config route123.6 / 41.9 kBThe declarative config the deprecated adapters use; it statically imports every plugin
@ceriousdevtech/vue-cerious-scroll1.2.02026-09-2120100.6 / 26.7 kB22 / 51 (43%)Component + composable

Bundle sizes: each library's entry for rendering a list, tree-shaken, dependencies bundled and Vue external - installed from npm at the version listed above and bundled with esbuild --bundle --splitting --minify --format=esm --external:vue, gzipped at level 9 and reported in kB (1000 bytes). The gzip figure covers the JavaScript and the stylesheet concatenated, so a row is what a page using that entry downloads; a dependency's lazy import() is a separate chunk and is not counted until the feature that needs it is used. Each number includes the stylesheet that entry needs: ours, vue-virtual-scroller and vlist (vlist/styles) ship theirs as a separate import, while vueuc and vue-cerious-scroll inject theirs from JavaScript. For the component libraries that is one component (RecycleScroller, VList, VVirtualList, VirtualList, CeriousScroll); for @tanstack/vue-virtual it is useVirtualizer including the @tanstack/virtual-core it depends on, and for vlist it is vlist/vue's useVList over the core, with plugins imported per feature: the bare core with its stylesheet is 12.8 kB gzip, 15.7 kB once the scrollbar plugin is added. The declarative vlist/config layer the deprecated adapters use statically imports every plugin, so it gets its own row at 41.9 kB. virtua is measured from its virtua/vue entry, since the package root is the React build. Ours is listed entry by entry - the package root with all six built-in extensions, the lean /core component, the headless useVirtualScroll composable, and that composable with the observer, keyboard and scrollbar ones - and each row's score counts only the features that entry ships, and it is measured from this package's built entry files on every docs build. Every other row is the published version listed, in the snapshot from 2026-10-29. vue-cerious-scroll bundles its runtime dependency (@ceriousdevtech/cerious-scroll) the way a consumer would.

Feature Matrix

Feature@pdanpdan
/virtual-scroll
vue-virtual-
scroller
@tanstack
/vue-virtual
virtuavueucvue-virtual-
scroll-list
vlist@ceriousdevtech/
vue-cerious-scroll
Vertical list✅✅✅✅✅✅✅✅
Horizontal list✅✅✅✅❌✅✅❌
Two-dimensional grid✅❌🟠✅❌❌🟠❌
Window (page) scrolling✅❌✅✅❌✅✅❌
Native scroll container (browser wheel/touch physics)✅✅✅✅✅✅✅❌
Fixed item sizes✅✅✅✅✅✅✅✅
Measured dynamic item sizes✅✅✅✅✅🟠✅✅
Measured rows without size estimates (no default-size first paint)❌❌❌❌❌❌❌✅
RTL✅❌🟠✅❌❌🟠❌
Sticky elements / headers✅❌❌❌❌❌✅❌
Keyboard navigation✅❌❌❌❌❌✅✅
Scroll snapping✅❌🟠❌❌❌🟠❌
Custom / virtual scrollbars✅❌🟠❌❌❌✅❌
Infinite loading✅🟠✅✅🟠🟠✅🟠
Scroll restoration (prepend)✅❌🟠✅❌❌🟠❌
Smooth programmatic scroll✅✅✅✅✅❌✅❌
SSR support✅❌✅✅❌❌❌❌
Beyond browser max element height✅❌❌❌❌❌✅❌
Table virtualization✅✅🟠🟠❌❌✅✅
Masonry layout (one scroll container)✅❌❌✅❌❌✅✅
Real table rows in flow + auto-size columns✅🟠❌❌❌❌❌✅
Index-only lists (no per-row data objects)✅❌✅❌❌❌❌✅
Custom item identity keys (getItemKey / getKey)❌❌✅✅❌❌❌❌
Automatic ARIA roles & item indices✅❌❌❌❌❌✅❌
Official siblings for other frameworks (React, Solid, …)❌❌✅✅❌❌✅✅
TypeScript✅✅✅✅✅❌✅✅
Feature score of 514715.52729.591036.522

✅ built-in  •  🟠 partial, limited, or requires custom code  •  ❌ not supported
Feature score weights each feature by how much of a library it is - 3 an engine of its own, 2 a built-in subsystem, 1 table stakes - with ✅ counting full weight, 🟠 half and ❌ none, out of 51.

Notes on the Partial Marks

🟠
@tanstack/vue-virtual

Headless: it provides the virtualizer and the application writes the markup, so every row not listed as ✅ is code you add. A two-axis grid is composed from two virtualizers, RTL is an isRtl flag, and scrollbars and snapping are not included. The entry is among the smallest here.

🟠
virtua

VGrid virtualizes both axes and VMasonry covers masonry; its README lists sticky headers and keyboard navigation as planned. Window scrolling and measured sizes are supported. One codebase serves five frameworks.

🟠
vue-virtual-scroll-list

Sizes come from an estimate cache (estimate-size) instead of measurement, so scrollbar accuracy is approximate. The last release dates from May 2023, the README targets Vue 2, and the package ships no TypeScript types.

🟠
vue-virtual-scroller

Infinite loading requires your own scroll listener. The component renders its own scroll container, so page scrolling needs a wrapper. Version 3.0 is maintained; the feature set is close to the Vue 2 version.

🟠
vueuc

VVirtualList is the list used by Naive UI. The author describes vueuc as a personal utility collection, so adopting it means depending on Naive UI's internal packages.

🟠
@ceriousdevtech/vue-cerious-scroll

It measures rows and includes masonry and real table layouts. Infinite loading is manual: detect the end, append, call updateTotalElements and re-render. It does not use the browser scrollport for input: wheel, touch and keyboard are handled on a hidden-overflow host. Horizontal lists, grids and sticky headers are listed as future work in its roadmap.

🟠
vlist

The grid is a single-axis layout: columns and a gap over a vertical list. Snapping is part of the carousel plugin. RTL covers vertical lists and tables; horizontal lists throw at creation. Prepending holds the visible rows in place only in reverse mode. The table renders div rows with resizable columns, and rows must exist as an array. The entry is vlist/vue over the core with plugins imported per feature; vlist/config, used by the deprecated adapters, imports every plugin and has its own row.

When to Choose Each One

  • @pdanpdan/virtual-scroll - the only entry here that combines a two-dimensional grid, window scrolling, RTL, sticky headers and keyboard navigation in one component, and the only one with a dedicated real-table-flow component. It also ships masonry, and with vlist it is one of two entries that virtualize past the browser's maximum element height. Index-only rows, ARIA roles, virtual scrollbars and a headless composable with extensions are included. The bundle is larger than the single-purpose libraries: 23.4 kB gzip for the package root and 18.0 kB for the lean /core component. The headless engine is 10.9 kB, 13.8 kB with the observer, keyboard and scrollbar composables, and 16.5 kB with every exported extension. Per kB gzip the single-purpose libraries lead (virtua 6.3, @tanstack/vue-virtual 2.7). The project is young and has a small community.
  • @ceriousdevtech/vue-cerious-scroll - the only other entry with real table rows; it also includes masonry and keyboard navigation. It is vertical only: no grid, horizontal mode, window scrolling, RTL, sticky, snapping, SSR or beyond-max support, and input is handled on a hidden-overflow host rather than the browser scrollport. At 26.7 kB gzip it is the largest default entry here.
  • vlist - a framework-agnostic core with Vue, React, Svelte and Solid entries and plugins for grid, masonry, table, tree, groups, selection, search, sortable, snapshots, transition, carousel and async data. With plugins imported per feature the core is 12.8 kB gzip, 15.7 kB with the scrollbar plugin; document scrolling is a plugin, the custom scrollbar is an overlay, and scroll.mode hands a list to a synthetic driver when it passes the browser's size limit. It has no two-dimensional grid, no horizontal RTL, no snapping outside the carousel, no real table rows and no forward-list prepend anchoring. First released this year.
  • vue-virtual-scroller - a conventional component API with a long release history. Window scrolling, RTL and two-dimensional layouts are not included.
  • @tanstack/vue-virtual - a plain list with full control of the markup, in the smallest bundle here. Grid, scrollbar and snapping code is yours to write.
  • virtua - small bundles, window scrolling, measured sizes, a two-dimensional grid and masonry. Sticky headers and keyboard navigation are planned, not shipped.
  • vueuc - VVirtualList is the list used by Naive UI; it is a reasonable choice inside that ecosystem.
  • vue-virtual-scroll-list - last released in May 2023; sizes are estimates rather than measurements.

Bottom Line

Any of these libraries handles a vertical list with known row sizes. The differences appear with a second axis, the page as the scroll container, sticky headers, keyboard support, or lists larger than the browser's height limit. The feature matrix shows which entry covers each case, and the size columns show what it costs.

Sources: npm registry, GitHub API and project docs, checked on 2026-10-29. vue-virtual-scroller  •  @tanstack/vue-virtual  •  virtua  •  vueuc  •  vue-virtual-scroll-list  •  @ceriousdevtech/vue-cerious-scroll  •  vlist (Vue adapter)