Skip to content

fix(VVirtualScroll): keep measured sizes when items change - #23326

Open
cestercian wants to merge 3 commits into
vuetifyjs:masterfrom
cestercian:fix/21452-virtual-scroll-jump
Open

cestercian wants to merge 3 commits into
vuetifyjs:masterfrom
cestercian:fix/21452-virtual-scroll-jump

Conversation

@cestercian

Copy link
Copy Markdown

Description

v-virtual-scroll dropped every measured row height whenever the items array changed. Anything not on screen then fell back to a short guess, the scroll height collapsed, and the list jumped.

Sizes are kept for rows that are still there. item-key is used when it is set, otherwise the item itself.

Fixes #21452

Markup:

<template>
  <v-app theme="dark">
    <v-container max-width="600">
      <div class="d-flex ga-2 mb-4">
        <v-btn @click="append">Append</v-btn>
        <v-btn @click="prepend">Prepend</v-btn>
      </div>

      <v-virtual-scroll :height="400" :items="items" item-key="id">
        <template #default="{ item }">
          <div
            class="d-flex align-center px-4"
            :style="{ height: `${item.height}px` }"
          >
            {{ item.title }}
          </div>
        </template>
      </v-virtual-scroll>
    </v-container>
  </v-app>
</template>

<script setup>
  import { ref } from 'vue'

  let nextId = 80

  const items = ref(Array.from({ length: 80 }, (_, index) => ({
    id: index,
    title: `Item ${index}`,
    height: index >= 30 && index < 50 ? 160 : 40,
  })))

  function append () {
    items.value.push({ id: nextId, title: `Item ${nextId}`, height: 72 })
    nextId += 1
  }

  function prepend () {
    items.value.unshift({ id: nextId, title: `Item ${nextId}`, height: 72 })
    nextId += 1
  }
</script>

Resetting every measured row when the list updates made the
scroll height collapse to a short estimate, so the viewport
jumped. Keep sizes for items that are still in the list.

fixes vuetifyjs#21452
@J-Sek

J-Sek commented Oct 28, 2026

Copy link
Copy Markdown
Contributor

Good playground. It shows the jump after [Prepend] is much less severe and scroll up is not having any jitter-like issues. I wonder if we can eliminate the move entirely.

Inserting items above the viewport left scrollTop unchanged, so
the visible row jumped. Restore it from item-key or identity,
and compensate when a row above the viewport is measured.
@cestercian

Copy link
Copy Markdown
Author

Yeah, the leftover move was scrollTop staying put when rows landed above the viewport. It now pins the first visible item by item-key (or identity) and shifts scrollTop by the size of the inserted rows, so Prepend should leave the anchored row where it is. Added a test for it too.

A zero size estimate made the first measured row look like it sat
above the viewport, so opening a select jumped scrollTop by one row.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug Report][3.8.6] v-virtual-scroll scroll position jums and scrolling becomes jittery after adding a new item to the list

2 participants