Implement virtual scrolling for a large list in Vue

Tests DOM cost awareness and viewport culling. Strong answer: mount only visible nodes plus overscan, recycle DOM on scroll, and preserve total scroll height with a spacer. Red flag: suggesting pagination or naive v-for without keys.
WHAT THIS TESTS: This question probes whether you treat the browser as a rendering engine with real limits, not just a data projection surface. Interviewers want to see that you know layout and paint time grow with DOM node count, and that Vue's reactivity system cannot virtualize what the browser still has to lay out. The core concept is viewport culling, sometimes called windowing.
A GOOD ANSWER COVERS: A strong response walks through five implementation steps in order. First, measure the viewport height and establish a fixed or estimated row height so you can compute how many items fit on screen at once. Second, determine a slice of the data array to render, adding an overscan buffer of one or two viewport heights above and below to prevent blank flashes during fast scrolling. Third, maintain the illusion of a full list by rendering a tall spacer element, or by using CSS transforms, so the container still reports the total scrollable height to the browser and native scrollbars behave correctly. Fourth, bind the scroll event and recalculate the visible slice efficiently, preferably inside a requestAnimationFrame loop or with a lightweight virtual scroll library, rather than triggering reactive updates on every pixel. Fifth, use keyed components or DOM recycling so that Vue reuses existing nodes instead of destroying and remounting them as the window shifts, which is the single biggest performance win.
COMMON WRONG ANSWERS: Suggesting pagination as a virtual scrolling alternative misses the point because the prompt asks for a scrolling list. Proposing v-for with key or v-memo alone is insufficient because those tools reduce update cost but do not reduce initial DOM size. Recommending infinite scroll or lazy image loading solves data fetching, not rendering. A dangerous red flag is manually detaching elements with display none; that keeps nodes in memory and layout tables, defeating the purpose.
LIKELY FOLLOW-UPS: The interviewer may ask how you handle variable row heights, which requires caching measured heights in a Map and adjusting the scroll offset math dynamically. They may ask how you would preserve scroll position across route changes, which involves persisting the offset index in a store or URL query. They might also ask about accessibility, specifically how aria-setsize and aria-posinset must be manually applied when the DOM no longer contains all items.
ONE CONCRETE EXAMPLE: Suppose you have a chat history with 10000 messages. You create a 600 pixel viewport container. Each message averages 50 pixels. You render only 12 visible messages plus 6 above and 6 below for overscan, totaling 24 DOM nodes instead of 10000. A 500000 pixel tall spacer sits behind the visible window. On scroll, you read scrollTop, divide by 50 to get the start index, slice the array, and pass the new slice to a keyed v-for. Vue diff reuses the 24 component instances, and requestAnimationFrame keeps the handler off the main thread during animation frames.
Read the original → material.angular.dev
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.