SSR Support

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

file · SSRExample.svelte mode · live running source
runtime · server
hydration · pending
range · 0-0
dom rows · 0
estimate · 60px
● ssr
Item 0

Initially rendered on server

ssr seed
Item 1

Initially rendered on server

hydrated row
Item 2

Initially rendered on server

measured client
Item 3

Initially rendered on server

ssr seed
Item 4

Initially rendered on server

hydrated row
Item 5

Initially rendered on server

measured client
Item 6

Initially rendered on server

ssr seed
Item 7

Initially rendered on server

hydrated row
Item 8

Initially rendered on server

measured client
Item 9

Initially rendered on server

ssr seed
Item 10

Initially rendered on server

hydrated row
Item 11

Initially rendered on server

measured client
Item 12

Initially rendered on server

ssr seed
Item 13

Initially rendered on server

hydrated row
Item 14

Initially rendered on server

measured client
Item 15

Initially rendered on server

ssr seed
Item 16

Initially rendered on server

hydrated row
Item 17

Initially rendered on server

measured client
Item 18

Initially rendered on server

ssr seed
Item 19

Initially rendered on server

hydrated row
Item 20

Initially rendered on server

measured client
items · 100
ssr · compatible
measure · after hydrate
dom nodes · 0
mode · sveltekit

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