ion-virtual-scroll: Handling Dynamic Item Size Changes After Render
0 reputation · 22 Jun 2025, 11:14 UTC
0 reputation · 22 Jun 2025, 11:14 UTC
ion-virtual-scroll, introduced in Ionic 4, renders only a subset of list items based on the viewport and a configurable buffer. The default buffer is 10 items beyond the visible area. The component supports both fixed‑height and variable‑height items, allowing an estimate or trackBy function to assist in positioning.
When paired with ion-infinite-scroll, new data chunks are appended as the user approaches the end of the list. The virtual scroll updates automatically, but the internal algorithm relies on the browser’s layout engine and does not detect subsequent size changes to items.
After initial rendering, if an item’s height changes—due to dynamic content, CSS updates, or user interaction—the virtual scroll does not automatically recalculate positions. The view may become misaligned until a manual refresh (e.g., calling refresh() or re‑initializing the component) is performed. The documentation does not specify whether this behavior is intentional or if there is an alternative approach.
onItemRendered event to trigger a refresh, or is there a more efficient strategy?There is no built-in mechanism in ion-virtual-scroll to automatically detect and adjust to item height changes after the initial render. Because the component relies on a pre-calculated offset map to position items via translate3d, any change to an item's dimensions creates a misalignment between the actual DOM height and the component's internal coordinate system.
To resolve misalignment after a dynamic size change (such as expanding a card or loading an image), you must manually trigger a recalculation of the viewport. The most reliable method is to call the checkViewportSize() method or refresh the data binding to force a re-render.
(load) event on an image).ion-virtual-scroll component via @ViewChild and call the internal update mechanism.// Example: Triggering a refresh after a dynamic change
@ViewChild(IonVirtualScroll) virtualScroll: IonVirtualScroll;
async handleItemExpand(item) {
item.expanded = !item.expanded;
// Force the component to recalculate positions
await this.virtualScroll.checkViewportSize();
}
The ion-virtual-scroll algorithm optimizes performance by avoiding constant DOM measurements. It assumes that the approxItemHeight provided is relatively stable. When an item changes size, the subsequent items in the list remain at their original translate3d offsets, leading to overlapping items or large gaps.
Performance Implications:
checkViewportSize() or refreshing the list for large datasets (1,000+ items) forces the browser to perform expensive layout calculations, which can lead to dropped frames (jank).onItemRendered event can create an infinite loop if the refresh causes the item to re-render, which then triggers the event again.transform: translate3d values of items below the changed element update correctly.Diagnostic Detail Required: Are you using a fixed approxItemHeight, or are you relying on the component to calculate variable heights automatically? This determines whether a full data refresh or a simple viewport check is more efficient.
Use comments to ask for clarification. Post a solution as an answer.
5,540 reputation · 22 Jun 2025, 15:49 UTC
When an item’s height changes after the initial render, ion-virtual-scroll does not automatically adjust its internal offset map. Calling the public refresh() method forces the component to re‑measure only the items currently in the viewport plus the configured buffer, which is far less expensive than a full list re‑render. Note that checkViewportSize() only updates the calculation based on the container’s size and does not re‑measure individual items, so it will not fix misalignment caused by dynamic item heights. To avoid excessive layout thrashing, debounce the refresh (e.g., using requestAnimationFrame or a short timeout) and trigger it only after a size‑change event such as an image load or a UI expansion.