Superfast Scroll
A practice demo for getting familiar with svelte.
Demo
Virtual Scroll List Demo
Initializing list items...
Iβm new to Svelte. This practice demo is for me to getting familiar with svelte store and reactive programming.
Technical Notes
This high-performance virtual scroll implementation combines battle-tested techniques with some experimental spice:
1. Data Structure Shenanigans
Our demo rides on a SkipList - not because itβs optimal, but because why not? (Confession: Your author just wanted an excuse to implement one π’)
- SkipList delivers O(log n) for search/insert/delete
- Reality check: A simple array + index map would smoke it for this use case (O(1) lookups)
- To spice things up, we added artificial delays (200ms) in data fetching. Did you notice? π
2. Ring Buffer Tango
We perform a carefully choreographed dance between two circular buffers:
DOM Recycling Ring
domRingHead
+ modulo arithmetic = infinite scrolling illusion- Extra buffer elements prevent visual hiccups
- Reuses a limited number of DOM nodes, significantly reducing memory usage and DOM operations
Data Window Provider Ring Buffer
- Provides buffering for asynchronous data loading
- Maintains upper and lower buffer zones for preloading and smooth scrolling
- Doubly-linked list enables O(1) window sliding
3. The Trilogy of Scroll Evolution
Version 1: The Sync Era π
Status: Deprecated but Nostalgic
Our initial βeverything worksβ prototype:
- Built for instant data access (latency comes from time complexity of data source implementation)
- Handle 100k items? Easy peasy lemon squeezy!
- Use same logic for both scroll and jump:
- Flow: User input β Position update β Provider processes data β Provider publishes new version β UI listens for version changes and fetches data
Version 2: Async Apocalypse π₯
Status: Briefly Lived Disaster
When we introduced async data loading in the data window provider (no actual delays added in data source):
Sync logic met async reality β π£
UI started shifting
translateY,
domRingHead
, and data updates entered a love triangle
Version 3: Redemption Arc π¦Έ
- Separated the logic for incremental scrolling and jumping again
- Incremental scrolling: uses a more direct and efficient approach, manipulating the DOM ring buffer and data directly to maintain visual continuity.
- Jumping: Completely resets the view state and waits for asynchronous data loading to complete
4. TranslateY Dual-Purpose Implementation
Container-level translateY:
- Applied to the entire list container
- The smooth talker: creates scrolling illusion
- Incrementally updated then reset like nothing happened
Item-level translateY:
- Applied to individual list items
- Items maintain fixed translateY values until recycled
- The precision artist: translateY = (mappedIndex Γ itemHeight)
- DOM elements play musical chairs without moving physically
This dual-transform approach enables several key optimizations:
- Minimizes DOM manipulation by changing only transform properties
- Avoids expensive reflow/repaint cycles in the browser
- Leverages GPU acceleration for smooth animations
- Allows for precise pixel positioning without layout calculations
Final score: 60 FPS smooth scrolling with 100k+ items (even with delays). Try that with standard lists π