Svelte Virtual List logo

SSR Support

Svelte Virtual List is fully compatible with server-side rendering (SSR) and SvelteKit.

Server-rendered
Item 0
Initially rendered on server (SSR)
Item 1
Initially rendered on server (SSR)
Item 2
Initially rendered on server (SSR)
Item 3
Initially rendered on server (SSR)
Item 4
Initially rendered on server (SSR)
Item 5
Initially rendered on server (SSR)
Item 6
Initially rendered on server (SSR)
Item 7
Initially rendered on server (SSR)
Item 8
Initially rendered on server (SSR)
Item 9
Initially rendered on server (SSR)
Item 10
Initially rendered on server (SSR)
Item 11
Initially rendered on server (SSR)
Item 12
Initially rendered on server (SSR)
Item 13
Initially rendered on server (SSR)
Item 14
Initially rendered on server (SSR)
Item 15
Initially rendered on server (SSR)
Item 16
Initially rendered on server (SSR)
Item 17
Initially rendered on server (SSR)
Item 18
Initially rendered on server (SSR)
Item 19
Initially rendered on server (SSR)
Item 20
Initially rendered on server (SSR)

How It Works

During SSR:

  • The component renders a minimal DOM structure
  • No scroll calculations occur (no viewport measurements on server)
  • Heights use the defaultEstimatedItemHeight estimate

On hydration:

  • The component measures the actual viewport
  • Heights are recalculated based on real measurements
  • Scroll position is initialized correctly

SvelteKit Integration

No special configuration needed. Just import and use:

<script lang="ts">
    import VirtualList from '@humanspeak/svelte-virtual-list'

    const { data } = $props()
</script>

<VirtualList items={data.items}>
    {#snippet renderItem(item)}
        <div>{item.text}</div>
    {/snippet}
</VirtualList>
<script lang="ts">
    import VirtualList from '@humanspeak/svelte-virtual-list'

    const { data } = $props()
</script>

<VirtualList items={data.items}>
    {#snippet renderItem(item)}
        <div>{item.text}</div>
    {/snippet}
</VirtualList>

Initial Data

For optimal UX, provide data during SSR to avoid loading states:

// +page.server.ts
export async function load() {
    const items = await fetchItems()
    return { items }
}
// +page.server.ts
export async function load() {
    const items = await fetchItems()
    return { items }
}

Performance Tips

  1. Provide realistic height estimates: Set defaultEstimatedItemHeight close to actual item heights
  2. Limit initial items: Fetch a reasonable first page (50-100 items)
  3. Use streaming: For large datasets, consider SvelteKit’s streaming features