
Description
Virtualize Vue Table final row or column models with reactive counts and scroll targets, stable keys, measurement, spacer geometry, sticky CSS, grid/flex widths, and infinite server data.
SKILL.md
This skill builds on @tanstack/table-core#core, getting-started, and table-state. Virtual consumes final Table models; it is not registered in tableFeatures.
Setup
import { computed, ref } from 'vue'
import { useVirtualizer } from '@tanstack/vue-virtual'
const scrollElement = ref<HTMLElement | null>(null)
const rows = computed(() => table.getRowModel().rows)
const rowVirtualizer = useVirtualizer(
computed(() => ({
count: rows.value.length,
getScrollElement: () => scrollElement.value,
estimateSize: () => 34,
getItemKey: (index) => rows.value[index]!.id,
overscan: 5,
})),
)
const virtualRows = computed(() => rowVirtualizer.value.getVirtualItems())
const totalSize = computed(() => rowVirtualizer.value.getTotalSize())
Core Patterns
Derive from current visible models
Rows come from table.getRowModel().rows; columns come from table.getVisibleLeafColumns(). Use computed options so counts and scroll targets update.
Implement the geometry
Give the scroll container a bounded height and positioning context, create a spacer using getTotalSize(), and translate/measure virtual items. Follow the grid/flex examples for dynamic row heights and sticky headers.
Coordinate infinite fetching
Fetch near the last virtual item only while totalFetched < serverRowCount and no request is active. Manual sorting means the server must return the sorted order and a sort change normally resets pages.
Common Mistakes
HIGH Passing a plain options snapshot
Wrong:
useVirtualizer({ count: rows.value.length, getScrollElement })
Correct:
useVirtualizer(computed(() => ({ count: rows.value.length, getScrollElement })))
Computed options keep the virtual range synchronized with Vue’s current model.
Source: examples/vue/virtualized-rows/src/App.vue
HIGH Virtualizing source arrays
Wrong:
const rows = computed(() => data.value)
Correct:
const rows = computed(() => table.getRowModel().rows)
Source arrays do not represent Table’s current filtering, sorting, expansion, or pagination.
Source: docs/framework/vue/guide/virtualization.md
HIGH Assuming Virtual provides CSS
Wrong:
<div v-for="item in virtualRows" :key="item.key">{{ rows[item.index].id }}</div>
Correct:
<div :style="{ height: `${totalSize}px`, position: 'relative' }"><div style="position:absolute"></div></div>
Virtual provides measurements, not spacer layout, transforms, sticky positioning, or Table column widths.
Source: examples/vue/virtualized-columns/src/App.vue
API Discovery
Inspect installed @tanstack/vue-table/dist/ and @tanstack/vue-virtual/dist/; use the maintained Vue examples for exact row, column, and infinite layout combinations.
More skills from the table repository
View all 29 skillsaggregation
perform data aggregation in TanStack Table
Jul 20Data AnalysisFrontendTanStackapi-not-found
diagnose TanStack Table API errors
Jul 20DebuggingFrontendTanStackclient-vs-server
manage TanStack Table data pipelines
Jul 20Data PipelineFrontendPerformanceTanStackcolumn-faceting
build faceted filter UIs
Jul 20Data VisualizationFrontendTanStackcolumn-filtering
implement column filtering in TanStack Table
Jul 20Data AnalysisFrontendTanStackcolumn-ordering
manage TanStack Table column ordering
Jul 20FrontendTanStackUI Components
More from TanStack
View publishercolumn-pinning
configure column pinning in TanStack Table
table
Jul 20CSSFrontendTanStackUI Componentscolumn-resizing
implement column resizing in TanStack Table
table
Jul 20FrontendTanStackUI Componentscolumn-sizing
configure column sizing in TanStack Table
table
Jul 20CSSFrontendTanStackUI Componentscolumn-visibility
manage column visibility in TanStack Table
table
Jul 20FrontendTanStackUI Componentscore
build data grids with TanStack Table
table
Jul 20Data AnalysisFrontendUI Componentscreate-table-hook
create reusable Vue table hooks
table
Jul 20FrontendUI ComponentsVue