How to Build a High‑Performance Fixed‑Height Virtual List in Vue

This article explains why rendering massive lists can freeze devices, introduces the concept of a fixed‑height virtual list that renders only visible items, and provides step‑by‑step Vue code to calculate visible ranges, handle scrolling, and fix off‑by‑one glitches.

Sohu Tech Products
Sohu Tech Products
Sohu Tech Products
How to Build a High‑Performance Fixed‑Height Virtual List in Vue

Fixed‑Height Virtual List

When pagination cannot be used and a list may contain tens of thousands of items, rendering the entire list can freeze the UI. A virtual list renders only the items that are visible in the viewport.

Principle

In a fixed‑height virtual list the height of each item is known. The number of items that fit in the viewport is computed as Math.ceil(containerHeight / itemHeight). Items outside the viewport are not rendered.

Implementation steps

Create a placeholder element inside the scroll container whose height equals list.length * itemHeight. Position it absolutely with z-index:-1 so it does not cover the visible items.

Measure the container height ( containerHeight) once the component is mounted.

Compute renderCount = Math.ceil(containerHeight / itemHeight). This is the number of items that must be rendered.

Derive the start index and end index for the current scroll position:

start = Math.floor(scrollTop / itemHeight);
end   = start + renderCount;
renderList = list.slice(start, end + 1);

Apply a vertical transform to the list wrapper so that the rendered slice stays aligned with the scroll position:

offset = scrollTop - (scrollTop % itemHeight);
transform: translate3d(0, ${offset}px, 0);

Vue component example (code only)

<template>
  <div>
    <div class="placeholder" :style="{ height: listHeight + 'px' }"></div>
    <div class="list-wrapper" :style="{ transform: getTransform }">
      <div
        class="card-item"
        v-for="(item, i) in renderList"
        :key="i"
        :style="{ height: itemSize + 'px', lineHeight: itemSize + 'px', backgroundColor: `rgba(0,0,0,${item / 100})` }">
        {{ item + 1 }}
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      listData: [/* large array */],
      itemSize: 100,
      start: 0,
      containerHeight: 0,
      offset: 0,
    };
  },
  computed: {
    listHeight() { return this.listData.length * this.itemSize; },
    renderCount() { return Math.ceil(this.containerHeight / this.itemSize); },
    end() { return this.start + this.renderCount; },
    renderList() { return this.listData.slice(this.start, this.end + 1); },
    getTransform() { return `translate3d(0,${this.offset}px,0)`; },
  },
  mounted() { this.containerHeight = this.$refs.content.clientHeight; },
  methods: {
    handleScroll(e) {
      const scrollTop = e.target.scrollTop;
      this.start = Math.floor(scrollTop / this.itemSize);
      this.offset = scrollTop - (scrollTop % this.itemSize);
    },
  },
};
</script>

<style scoped>
.content { height: 100vh; overflow: auto; position: relative; }
.placeholder { position: absolute; left: 0; top: 0; right: 0; z-index: -1; }
</style>

Caveats

The scroll event fires before the start index is updated, which can cause a one‑item overshoot. Applying the offset transform eliminates the visual glitch.

All calculations assume a constant item height; variable heights require a different strategy (covered in a subsequent article).

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

frontendperformanceVuevirtual listscroll optimizationfixed height
Sohu Tech Products
Written by

Sohu Tech Products

A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.