diff --git a/docs/api/virtualizer.md b/docs/api/virtualizer.md index 7ac66acc..92845303 100644 --- a/docs/api/virtualizer.md +++ b/docs/api/virtualizer.md @@ -319,3 +319,9 @@ scrollRect: Rect ``` Current `Rect` of the scroll element. + +```tsx +shouldAdjustScrollPositionOnItemSizeChange: undefined | ((item: VirtualItem, delta: number, instance: Virtualizer) => boolean) +``` + +The shouldAdjustScrollPositionOnItemSizeChange method enables fine-grained control over the adjustment of scroll position when the size of dynamically rendered items differs from the estimated size. When jumping in the middle of the list and scrolling backward new elements may have a different size than the initially estimated size. This discrepancy can cause subsequent items to shift, potentially disrupting the user's scrolling experience, particularly when navigating backward through the list. diff --git a/packages/virtual-core/src/index.ts b/packages/virtual-core/src/index.ts index 6083d506..b3be9dab 100644 --- a/packages/virtual-core/src/index.ts +++ b/packages/virtual-core/src/index.ts @@ -290,6 +290,13 @@ export class Virtualizer< scrollOffset: number scrollDirection: ScrollDirection | null = null private scrollAdjustments: number = 0 + shouldAdjustScrollPositionOnItemSizeChange: + | undefined + | (( + item: VirtualItem, + delta: number, + instance: Virtualizer, + ) => boolean) measureElementCache = new Map() private observer = (() => { let _ro: ResizeObserver | null = null @@ -666,7 +673,11 @@ export class Virtualizer< const delta = size - itemSize if (delta !== 0) { - if (item.start < this.scrollOffset + this.scrollAdjustments) { + if ( + this.shouldAdjustScrollPositionOnItemSizeChange !== undefined + ? this.shouldAdjustScrollPositionOnItemSizeChange(item, delta, this) + : item.start < this.scrollOffset + this.scrollAdjustments + ) { if (process.env.NODE_ENV !== 'production' && this.options.debug) { console.info('correction', delta) }