Back to Playground
Performance

Virtual Scrolling

Efficiently render large lists by only rendering visible items. Improves performance for thousands of items.

ReactTypeScriptOptimization

Virtual Scrolling

Virtual scrolling only renders visible items, dramatically improving performance for large lists. Try scrolling through thousands of items smoothly!

PERFORMANCE

60 FPS

Smooth scrolling

DOM NODES

~20

vs 1,000 regular

MEMORY

95%

Less memory used

Virtual Scrolling (Optimized)

#1User Item 1 - ac89jd
#2Product Item 2 - 87h8aa
#3Order Item 3 - 9f6nbp
#4Invoice Item 4 - xkjxtg
#5Report Item 5 - qlfkzm
#6Document Item 6 - ytcz
#7User Item 7 - nbpdi
#8Product Item 8 - ljf9zw
#9Order Item 9 - 3e64ng
#10Invoice Item 10 - a1woh
#11Report Item 11 - uu8kp
#12Document Item 12 - mcoovc
#13User Item 13 - phplak
#14Product Item 14 - 37gtvm
Rendering: 0 / 1,000
Viewing: #1 - #14

How It Works

1

Calculate Visible Range

Determine which items are currently in the viewport based on scroll position

2

Render Only Visible Items

Only create DOM nodes for items that are visible (plus a small buffer)

3

Position with Transform

Use CSS transforms to position items correctly without rendering everything

4

Update on Scroll

Recalculate and re-render as the user scrolls through the list

Perfect For

✓ Large Data Tables

Thousands of rows without lag

✓ Infinite Scroll

Social media feeds and timelines

✓ Chat Applications

Long message histories

✓ File Explorers

Directories with many files

Code

const VirtualList = ({ items, itemHeight }) => {
  const [scrollTop, setScrollTop] = useState(0)
  const containerHeight = 600
  
  const startIndex = Math.floor(scrollTop / itemHeight)
  const endIndex = Math.ceil(
    (scrollTop + containerHeight) / itemHeight
  )
  
  const visibleItems = items.slice(
    startIndex,
    endIndex
  )
  
  return (
    <div
      style={{ height: containerHeight, overflow: 'auto' }}
      onScroll={(e) => setScrollTop(e.target.scrollTop)}
    >
      <div style={{ height: items.length * itemHeight }}>
        {visibleItems.map((item, i) => (
          <div
            key={startIndex + i}
            style={{
              position: 'absolute',
              top: (startIndex + i) * itemHeight
            }}
          >
            {item}
          </div>
        ))}
      </div>
    </div>
  )
}