Skip to main content

Virtual Scroll

Use the virtual option to virtually render a large number of panels and significantly reduce memory usage.

import Flicking from "@egjs/flicking";
import "@egjs/flicking/dist/flicking.css";
import "./styles.css";

const TOTAL_PANELS = 1000;
const _COLORS = ["#3e8ed0", "#00d1b2", "#f14668", "#ffe08a", "#48c78e", "#9c27b0", "#ff5722"];

// Virtual mode: 1000 panels
const virtualFlicking = new Flicking("#flick-virtual", {
  align: "prev",
  panelsPerView: 3,
  virtual: {
    renderPanel: (panel, index) => `<div class="panel-inner color-${index % 7}">Panel ${index + 1}</div>`,
    initialPanelCount: TOTAL_PANELS,
    cache: true,
    panelClass: "flicking-panel"
  }
});

// Normal mode: 100 panels (for comparison)
// In normal mode, panels are created as HTML elements
const normalFlicking = new Flicking("#flick-normal", {
  align: "prev"
});

// Update DOM element count
function updateDomCounts() {
  const virtualCount = document.querySelectorAll("#flick-virtual .flicking-panel").length;
  const normalCount = document.querySelectorAll("#flick-normal .flicking-panel").length;

  document.getElementById("virtual-count").textContent = virtualCount;
  document.getElementById("normal-count").textContent = normalCount;
}

virtualFlicking.on("move", updateDomCounts);
virtualFlicking.on("ready", updateDomCounts);
normalFlicking.on("ready", updateDomCounts);

updateDomCounts();

Summary

Key Options

OptionTypeDefaultDescription
virtualVirtualOptions | nullnullVirtual rendering settings
panelsPerViewnumber-1Number of panels visible in the viewport (required when using virtual)

VirtualOptions Properties

PropertyTypeDefaultDescription
renderPanel(panel, index) => string-Function that returns panel innerHTML
initialPanelCountnumber-1Initial virtual panel count
cachebooleanfalseWhether to cache rendering results
panelClassstring"flicking-panel"Panel element class name

Mode Comparison

ModeDOM Elements with 1000 panelsMemory UsageInitial Rendering
Normal mode1000HighSlow
Virtual mode~4 (panelsPerView + 1)LowFast

Details

Virtual Rendering Principle

Virtual mode keeps only the visible panels + buffer in the actual DOM:

// 1000 logical panels, only 4 actual DOM elements
const flicking = new Flicking("#el", {
panelsPerView: 3, // Required: number of visible panels
virtual: {
renderPanel: (panel, index) => `Panel ${index + 1}`,
initialPanelCount: 1000,
cache: true // Prevent re-rendering of the same panel
}
});

During scrolling, DOM elements are recycled and replaced with new panel content. This approach can handle 1,000, 10,000 or more panels with constant memory usage.

Required Setting: panelsPerView

panelsPerView Required

To use the virtual option, you must set panelsPerView to a positive number.
If panelsPerView: -1 (auto), virtual is ignored.

// Correct setting
{ panelsPerView: 3, virtual: { ... } } // Works

// Incorrect setting
{ panelsPerView: -1, virtual: { ... } } // virtual is ignored

renderPanel Callback

renderPanel is called whenever a panel appears on screen and returns its innerHTML:

virtual: {
renderPanel: (panel, index) => {
// index: 0-based panel index
return `
<img src="/images/item-${index}.jpg" />
<span>Item ${index + 1}</span>
`;
},
initialPanelCount: 1000
}

cache Option

// cache: true (recommended for static content)
virtual: {
renderPanel: (panel, index) => `Panel ${index}`,
cache: true // Reuse previously rendered panel content
}

// cache: false (for dynamic content)
virtual: {
renderPanel: (panel, index) => `Panel ${index}: ${Date.now()}`,
cache: false // Re-render every time
}

VirtualManager Methods

You can add/remove virtual panels at runtime:

// Add panels
flicking.virtual.append(100); // Append 100 to the end
flicking.virtual.prepend(50); // Prepend 50 to the front
flicking.virtual.insert(10, 20); // Insert 20 at index 10

// Remove panels
flicking.virtual.remove(0, 10); // Remove 10 starting from index 0

Use Cases

When should you use virtual?

Recommended:

  • When there are many panels (50+)
  • Image galleries, product lists, and other large datasets
  • Infinite scroll implementation
  • Mobile environments with memory constraints

Not necessary:

  • When there are few panels (less than 10)
  • When complex panel interactions are needed
  • When panel content is highly dynamic

Notes

Framework Differences

In React and Vue, renderPanel returns an HTML string. If you need component rendering, consider the renderOnlyVisible option instead.

renderPanel Performance

renderPanel is called frequently during scrolling. Avoid complex computations or DOM manipulations, and leverage cache: true.