Framework7 List View — Contacts, Media Lists, Swipe Actions, and Grouping
In this tutorial, you will learn about Framework7 List View. We cover key concepts, practical examples, and best practices to help you master this topic.
Framework7 list views render data in scrollable lists with support for media items, swipe actions, accordion expansion, grouping with section dividers, and virtual rendering for thousands of items.
What You'll Know
- Simple and media list views
- Swipe actions (delete, mark, etc.)
- Accordion expandable lists
- Virtual lists for large datasets
- List grouping with dividers
Why It Matters
Lists are the most common mobile UI pattern — contacts, messages, settings, search results. Framework7 lists handle touch interactions, swipe actions, and performance optimization for large datasets.
Real-World Use
A messaging app with a contact list showing avatars and last message time, swipe left to delete or archive a conversation, and a virtual list rendering 10,000+ contacts with smooth scrolling.
List View Architecture
flowchart TD
A[List View] --> B[Simple List]
A --> C[Media List]
A --> D[Contact List]
A --> E[Virtual List]
B --> F[Items with Icons]
C --> G[Items with Images]
D --> H[Alphabetical Groups]
E --> I[10k+ Items]
A --> J[Swipe Actions]
A --> K[Accordion]
style A fill:#e6f3ff,stroke:#4a90d9,stroke-width:2px
Simple List
<div class="page-content">
<div class="list">
<ul>
<li>
<a href="/details/" class="item-link item-content">
<div class="item-media"><i class="icon f7-icons">folder</i></div>
<div class="item-inner">
<div class="item-title">Documents</div>
<div class="item-after">15</div>
</div>
</a>
</li>
<li>
<a href="/details/" class="item-link item-content">
<div class="item-media"><i class="icon f7-icons">photo</i></div>
<div class="item-inner">
<div class="item-title">Photos</div>
<div class="item-after">42</div>
</div>
</a>
</li>
<li>
<a href="/details/" class="item-link item-content">
<div class="item-media"><i class="icon f7-icons">music</i></div>
<div class="item-inner">
<div class="item-title">Music</div>
<div class="item-after">128</div>
</div>
</a>
</li>
</ul>
</div>
</div>
Expected output: A simple list with three items. Each item has an icon, title, and a count badge on the right. Tapping an item follows the link.
Media List
<div class="list media-list">
<ul>
<li>
<a href="/detail/" class="item-link item-content">
<div class="item-media">
<img src="https://picsum.photos/80/80?random=1" width="80" />
</div>
<div class="item-inner">
<div class="item-title-row">
<div class="item-title">Alice Johnson</div>
<div class="item-after">2:45 PM</div>
</div>
<div class="item-subtitle">Senior Developer</div>
<div class="item-text">
Hey, I reviewed the pull request. Looks good but we need to update the tests before merging.
</div>
</div>
</a>
</li>
<li>
<a href="/detail/" class="item-link item-content">
<div class="item-media">
<img src="https://picsum.photos/80/80?random=2" width="80" />
</div>
<div class="item-inner">
<div class="item-title-row">
<div class="item-title">Bob Smith</div>
<div class="item-after">Yesterday</div>
</div>
<div class="item-subtitle">Product Manager</div>
<div class="item-text">
Can we schedule a meeting to discuss the Q3 roadmap? I have some ideas about the new features.
</div>
</div>
</a>
</li>
</ul>
</div>
Expected output: A media list with avatars, name, role, timestamp, and message preview. The image is 80x80 pixels and the text shows two lines before truncating.
Swipe Actions
<div class="list media-list">
<ul>
<li class="swipeout">
<div class="swipeout-content item-content">
<div class="item-media"><img src="avatar.jpg" width="50" /></div>
<div class="item-inner">
<div class="item-title-row">
<div class="item-title">Message 1</div>
<div class="item-after">10:30 AM</div>
</div>
<div class="item-text">This is a message preview for swipe demonstration.</div>
</div>
</div>
<div class="swipeout-actions">
<div class="swipeout-actions-inner">
<a href="#" data-confirm="Delete this item?" class="swipeout-delete">Delete</a>
<a href="#" class="swipeout-actions-close" style="background: #4caf50">Mark Read</a>
<a href="#" style="background: #ff9800">Archive</a>
</div>
</div>
</li>
<!-- More items -->
</ul>
</div>
// Swipeout events
$$(document).on('swipeout:delete', '.swipeout', function(e) {
var item = e.detail.item;
console.log('Item deleted');
});
$$(document).on('swipeout:close', '.swipeout', function(e) {
console.log('Swipeout closed');
});
// Programmatic swipeout
app.swipeout.open(el);
app.swipeout.close(el);
app.swipeout.delete(el);
Expected output: Swiping left on a list item reveals action buttons (Delete, Mark Read, Archive). The buttons have background colors and the delete action shows a confirmation dialog.
Virtual List
// Virtual list for large datasets
<div class="page">
<div class="navbar">...</div>
<div class="page-content">
<div class="list virtual-list" id="contacts-list"></div>
</div>
</div>
// Generate data
var items = [];
for (var i = 1; i <= 10000; i++) {
items.push({
name: 'Contact ' + i,
email: 'contact' + i + '@example.com',
avatar: 'https://picsum.photos/50/50?random=' + i
});
}
// Initialize virtual list
var virtualList = app.virtualList.create({
el: '#contacts-list',
items: items,
height: 73, // Item height in px
renderItem: function(item) {
return '<li>' +
'<a href="/contact/' + item.email + '/" class="item-link item-content">' +
'<div class="item-media"><img src="' + item.avatar + '" width="50" /></div>' +
'<div class="item-inner">' +
'<div class="item-title-row">' +
'<div class="item-title">' + item.name + '</div>' +
'</div>' +
'<div class="item-subtitle">' + item.email + '</div>' +
'</div>' +
'</a>' +
'</li>';
},
on: {
itemBeforeInsert: function(item) {
// Called before each item is inserted into DOM
}
}
});
// Append more items
virtualList.appendItems(moreItems);
// Search/filter
virtualList.filterItems(function(item) {
return item.name.toLowerCase().indexOf(searchTerm) > -1;
});
Expected output: A virtual list renders only visible items (about 20 at a time) while supporting 10,000+ data items. Scrolling is smooth because DOM elements are recycled.
Accordion List
<div class="list accordion-list">
<ul>
<li class="accordion-item">
<a href="#" class="item-link item-content accordion-item-toggle">
<div class="item-inner">
<div class="item-title">What is Framework7?</div>
</div>
</a>
<div class="accordion-item-content">
<div class="block">
<p>Framework7 is a full-featured HTML framework for building iOS and Android apps.</p>
</div>
</div>
</li>
<li class="accordion-item">
<a href="#" class="item-link item-content accordion-item-toggle">
<div class="item-inner">
<div class="item-title">How do I install it?</div>
</div>
</a>
<div class="accordion-item-content">
<div class="block">
<p>Include the Framework7 CSS and JS files from CDN or install via npm.</p>
</div>
</div>
</li>
<li class="accordion-item accordion-item-expanded">
<a href="#" class="item-link item-content accordion-item-toggle">
<div class="item-inner">
<div class="item-title">Is it free?</div>
</div>
</a>
<div class="accordion-item-content">
<div class="block">
<p>Yes, Framework7 is open source under the MIT license.</p>
</div>
</div>
</li>
</ul>
</div>
// Accordion events
$$(document).on('accordion:open', '.accordion-item', function(e) {
console.log('Panel opened');
});
$$(document).on('accordion:close', '.accordion-item', function(e) {
console.log('Panel closed');
});
Expected output: An accordion list where tapping a question expands the answer below it. Multiple items can be open simultaneously or the accordion can be set to single-open mode.
List Grouping with Dividers
<div class="list">
<ul>
<li class="list-group-title">A</li>
<li>
<a href="#" class="item-link item-content">
<div class="item-inner"><div class="item-title">Alice</div></div>
</a>
</li>
<li>
<a href="#" class="item-link item-content">
<div class="item-inner"><div class="item-title">Andrew</div></div>
</a>
</li>
<li class="list-group-title">B</li>
<li>
<a href="#" class="item-link item-content">
<div class="item-inner"><div class="item-title">Bob</div></div>
</a>
</li>
<li>
<a href="#" class="item-link item-content">
<div class="item-inner"><div class="item-title">Brenda</div></div>
</a>
</li>
<li class="list-group-title">C</li>
<li>
<a href="#" class="item-link item-content">
<div class="item-inner"><div class="item-title">Charlie</div></div>
</a>
</li>
</ul>
</div>
Expected output: Items are grouped alphabetically with sticky section headers (A, B, C) that remain at the top while scrolling through their section.
Sortable List
<div class="list sortable">
<ul>
<li>
<div class="item-content">
<div class="item-inner"><div class="item-title">Item 1</div></div>
<div class="sortable-handler"></div>
</div>
</li>
<li>
<div class="item-content">
<div class="item-inner"><div class="item-title">Item 2</div></div>
<div class="sortable-handler"></div>
</div>
</li>
<li>
<div class="item-content">
<div class="item-inner"><div class="item-title">Item 3</div></div>
<div class="sortable-handler"></div>
</div>
</li>
</ul>
</div>
// Enable sortable mode
app.sortable.toggle('.sortable');
// Sortable events
$$(document).on('sortable:sort', '.sortable', function(e) {
var index = e.detail.from;
console.log('Item moved from', e.detail.from, 'to', e.detail.to);
});
// Get sorted order
var sortedItems = app.sortable.getItems('.sortable');
Expected output: A sortable list where dragging the handle reorders items. The sortable:sort event fires with the original and new positions.
Common Mistakes
Not wrapping list items in ul - Framework7 list items must be inside
<ul>elements. Using<div>breaks the list's built-in styling and behaviors.Forgetting swipeout-content class - Swipeout items need the swipeout-content class on the content wrapper. Without it, the swipe actions do not appear.
Using virtual list without height - Virtual list requires the exact pixel height of each item. Incorrect height causes jumpy scrolling or blank items.
Over-nesting list elements - List items have a specific structure: li > div.item-content > div.item-media + div.item-inner. Stray elements break the layout.
Not destroying virtual list on page removal - Virtual lists use event listeners and DOM recycling. Call virtualList.destroy() when the page is removed to prevent memory leaks.
Practice Questions
- What is the difference between a simple list and a media list?
- How do you add swipe actions to a list item?
- What is a virtual list and when should you use it?
- How do you create an accordion list?
- How do you group list items alphabetically?
Challenge: Build a contacts app with: a virtual list rendering 5,000 contacts with name, email, and avatar, alphabetical grouping with sticky section headers, swipe actions for delete and favorite, search input that filters the virtual list in real time, and a sortable mode toggle for manual reordering.
FAQ
Mini Project
Build a message inbox with: a media list showing contact avatar, name, message preview, and timestamp, swipe actions (Archive, Delete, Mark as Read), pull-to-refresh to load new messages, search bar to filter messages, and a toggle to switch between regular list and grouped-by-date view.
What's Next
Lists display data. Learn how Framework7 Form Elements collect user input with text fields, toggles, sliders, date pickers, and smart select forms.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro