Framework7 Virtual List: Rendering 10,000 Items Without Performance Collapse
Framework7's Virtual List renders only visible items, reducing DOM nodes from thousands to ~30. Learn configuration, key requirements, and common pitfalls.
16 Apr 2026, 17:26 UTC

The Performance Problem with Large Lists
When building mobile apps with Framework7, rendering lists with thousands of items can bring even modern devices to a crawl. A typical approach of creating a DOM element for each list item fails because browsers struggle with memory and layout calculations when hundreds or thousands of elements exist simultaneously.
How Virtual List Solves This
Framework7's Virtual List component solves this by rendering only what's visible on screen plus a small buffer—typically 20-30 items regardless of your total dataset size. This means a list with 10,000 items performs nearly as well as one with 30 items.
Basic Configuration Example
Here’s a working implementation using Framework7’s <f7-virtual-list> component:
<f7-virtual-list
items='items'
:item-height='80'
:render-item='renderItem'
></f7-virtual-list>
<script>
const items = [];
for (let i = 0; i < 10000; i++) {
items.push({ id: i, title: `Item ${i}` });
}
function renderItem(item) {
return `
<f7-list-item
key='${item.id}'
data-id='${item.id}'
>
<div class='item-title'>${item.title}</div>
</f7-list-item>
`;
}
</script>
Key attributes:
items- Your data array bound to the componentitem-height- Fixed height in pixels (required for proper scroll calculation)render-item- Function returning HTML for each item
Why Item Height Matters
Virtual List calculates scroll position based on knowing each item’s height. If items have variable heights, you must either:
- Set a consistent fixed height via
item-height - Enable the
auto-heightprop (Framework7 7.x only) - Use CSS to ensure all items have the same computed height
Without consistent sizing, the scrollbar will jump erratically as you scroll because the component can’t accurately determine how far down in the list you are.
Handling Interactive Elements
Interactive elements like buttons or switches require special attention. Because virtual list recycles DOM elements, you must preserve state manually:
<script>
const itemStates = {};
function renderItem(item) {
const isActive = itemStates[item.id] || false;
return `
<f7-list-item key='${item.id}'>
<div class='item-title'>${item.title}</div>
<f7-button
class='state-button'
data-id='${item.id}'
>
${isActive ? 'Active' : 'Inactive'}
</f7-button>
</f7-list-item>
`;
}
// Handle button clicks
document.addEventListener('click', (e) => {
if (e.target.classList.contains('state-button')) {
const id = e.target.dataset.id;
itemStates[id] = !itemStates[id];
// Force re-render of this item
virtualList.item(id).refresh();
}
});
</script>
Common Pitfalls and How to Avoid Them
Missing Key Attributes
Every <f7-list-item> rendered by virtual list needs a unique key prop. Without it, Framework7 can’t properly track which items are which during recycling, causing items to appear in wrong positions or duplicate content.
Nested Scrollable Containers
Placing a virtual list inside another scrollable container (like a page’s fixed panel or a custom scrollable div) often breaks scroll calculations. The virtual list needs direct access to the viewport’s scroll position to work correctly. If you must nest, consider using Framework7’s scrollable component with explicit height constraints.
Stale Data After Updates
When modifying your data array, always call virtualList.refresh() to force the component to recalculate. Simply updating the array won’t trigger a re-render of the virtual list’s internal state.
Auto-Height Limitations
The auto-height feature in Framework7 7.x allows variable item heights, but it has tradeoffs: it requires measuring each item (performance cost) and can cause layout thrashing during rapid scrolling. For best performance, stick with fixed heights when possible.
Verification Checklist
- DOM Node Count: Open browser devtools and verify only ~20-30 list item elements exist regardless of total items
- Scroll Smoothness: Scrolling should feel instant with no frame drops
- Key Uniqueness: Each item must have a distinct key prop to prevent rendering bugs
- Height Consistency: Toggle off fixed height and observe scroll position jumps
- Interactive State: Buttons/toggles should maintain state when scrolled out of view and back
Version Differences to Note
In Framework7 6.x, virtual list functionality was exposed through the virtual-list prop on the standard <f7-list> component. Framework7 7.x introduced the dedicated <f7-virtual-list> element with a cleaner API. If you’re maintaining legacy code, check which version you’re using before implementing.
Practical Implementation Tips
- Start Simple: Begin with fixed-height items and basic text content
- Measure Performance: Use browser performance tools to verify DOM node count stays low
- Handle Empty States: Provide a fallback UI when your items array is empty
- Consider Pagination: For extremely large datasets (100k+ items), consider combining virtual list with pagination to reduce memory footprint further
Bottom Line: Virtual List is essential for any Framework7 app displaying large datasets. The key is understanding its requirements—consistent item heights, unique keys, and proper state management for interactive elements. When implemented correctly, it transforms an unusable list into a smooth, native-like experience.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.