T
TanStack•10mo ago
correct-apricot

Scrolling issues on iOS only

Hello, I'm trying to use the tanstack virtual list in my svelte 5 application, but I've been running into an issue that only happens on iOS. Basically when you scroll, it doesn't have any momentum on iOS. I've tested it on an android phone, MacOS, and linux and it doesnt have the issue. Anyone have any ideas on how to fix this? Here is my code:
<script>
....
const virtualizer = $derived(
createVirtualizer<HTMLDivElement, HTMLDivElement>({
count: selected_tab.value === 'train' ? train_data.length : bus_data.length,
getScrollElement: () => list_div,
estimateSize: () => item_components[type][1],
paddingEnd: 5,
debug: true
})
);
const virtual_list_items = $derived($virtualizer.getVirtualItems());

// https://github.com/TanStack/virtual/issues/866
let mounted = $state(false);
$effect(() => {
if (!mounted && list_div !== null) {
mounted = true;
$virtualizer._willUpdate();
}
});

$effect(() => {
if (list_item_els[selected_tab.value].length) {
list_item_els[selected_tab.value].forEach((el) => $virtualizer.measureElement(el));
}
});
....
</script>

<div
bind:this={list_div}
class={`overflow-y-auto overscroll-contain text-base ${class_name ?? ''}`}
>
<div style="position: relative; height: {$virtualizer.getTotalSize()}px; width: 100%;">

<div
class="divide-y divide-neutral-800 border-y border-neutral-800"
style="position: absolute; top: 0; left: 0; width: 100%; transform: translateY({virtual_list_items[0]
? virtual_list_items[0].start
: 0}px);"
>

{#each virtual_list_items as row, idx (row.index)}
<div
bind:this={list_item_els[selected_tab.value][idx]}
data-index={row.index}
class="relative w-full"
>
{row.index}
</div>
{/each}

</div>
</div>
</div>
<script>
....
const virtualizer = $derived(
createVirtualizer<HTMLDivElement, HTMLDivElement>({
count: selected_tab.value === 'train' ? train_data.length : bus_data.length,
getScrollElement: () => list_div,
estimateSize: () => item_components[type][1],
paddingEnd: 5,
debug: true
})
);
const virtual_list_items = $derived($virtualizer.getVirtualItems());

// https://github.com/TanStack/virtual/issues/866
let mounted = $state(false);
$effect(() => {
if (!mounted && list_div !== null) {
mounted = true;
$virtualizer._willUpdate();
}
});

$effect(() => {
if (list_item_els[selected_tab.value].length) {
list_item_els[selected_tab.value].forEach((el) => $virtualizer.measureElement(el));
}
});
....
</script>

<div
bind:this={list_div}
class={`overflow-y-auto overscroll-contain text-base ${class_name ?? ''}`}
>
<div style="position: relative; height: {$virtualizer.getTotalSize()}px; width: 100%;">

<div
class="divide-y divide-neutral-800 border-y border-neutral-800"
style="position: absolute; top: 0; left: 0; width: 100%; transform: translateY({virtual_list_items[0]
? virtual_list_items[0].start
: 0}px);"
>

{#each virtual_list_items as row, idx (row.index)}
<div
bind:this={list_item_els[selected_tab.value][idx]}
data-index={row.index}
class="relative w-full"
>
{row.index}
</div>
{/each}

</div>
</div>
</div>
2 Replies
correct-apricot
correct-apricotOP•9mo ago
for the example im just showing row.index but the same bug happens with the real data (with dynamic height) that goes inside the list. I ended up building my own virtual list 😹
equal-aqua
equal-aqua•9mo ago
Great, if something happy to accept any pull request to fix the issues on tanstack side

Did you find this page helpful?