Skip to content

Virtualization

Virtualized.svelte
<script lang="ts">
import { MaterialSvelteTable, type MRT_ColumnDef } from 'material-svelte-tanstack-table';
import { type Person, makeData } from '../data/makeData';
const columns: MRT_ColumnDef<Person>[] = [
{ accessorKey: 'firstName', header: 'First Name' },
{ accessorKey: 'lastName', header: 'Last Name' },
{ accessorKey: 'email', header: 'Email', size: 260 },
{ accessorKey: 'city', header: 'City' },
{ accessorKey: 'state', header: 'State' },
];
// 10,000 rows, but only the ones in view are in the DOM
const data = makeData(10_000);
</script>
<MaterialSvelteTable
options={{
columns,
data,
enablePagination: false,
enableRowNumbers: true,
enableRowVirtualization: true,
tableContainerProps: { style: 'max-height: 480px' },
}}
/>

enableRowVirtualization keeps only the visible rows in the DOM. It uses a grid layout with a sticky header, so give the table a height:

options={{
columns,
data,
enablePagination: false,
enableRowVirtualization: true,
tableContainerProps: { style: 'max-height: 600px' },
}}

enableColumnVirtualization does the same for wide tables. Pinned columns always stay rendered. Both can be used together.

rowVirtualizerOptions and columnVirtualizerOptions (an object, or a function of { table }) are passed to TanStack Virtual: for example overscan or estimateSize. To scroll programmatically, keep a reference to the virtualizer:

<script lang="ts">
const rowVirtualizerInstanceRef: { current: MRT_RowVirtualizer | null } = { current: null };
</script>
<button onclick={() => rowVirtualizerInstanceRef.current?.scrollToIndex(500)}>Go to row 500</button>
<MaterialSvelteTable options={{ columns, data, enableRowVirtualization: true, rowVirtualizerInstanceRef }} />
  • Whether to virtualize is decided when the table is created and cannot change afterwards.
  • Rows are measured as they render, so varying row heights work. Pass estimateSize if your rows are far from the default heights (37, 58 and 73 pixels for compact, comfortable and spacious).
  • Detail panels are supported: each panel counts as a virtual item between rows.