Framework7 Toolbar and Tabbar — Bottom Navigation, Icons, and Badges
In this tutorial, you will learn about Framework7 Toolbar and Tabbar. We cover key concepts, practical examples, and best practices to help you master this topic.
Framework7 toolbar and tabbar create bottom navigation bars with tab links, icons, badges, and integrated tab switching — essential for mobile app navigation with iOS and Material Design styling.
What You'll Learn
- Creating toolbars and tabbars
- Tab links with icons and labels
- Badge notifications on tabs
- Tab bar styling (iOS vs Material)
- Toolbar with buttons and controls
Why It Matters
Bottom navigation is the primary navigation pattern in mobile apps. Framework7 tabbars provide iOS and Material Design styled bars with built-in tab switching, active state management, and badge support.
Real-World Use
A social media app with a bottom tabbar (Home, Search, Notifications with badge, Profile) where each tab shows a different view, and the toolbar displays contextual action buttons within specific pages.
Tabbar Architecture
flowchart LR
A[Tabbar] --> B[Tab 1: Home]
A --> C[Tab 2: Search]
A --> D[Tab 3: Notifications]
A --> E[Tab 4: Profile]
B --> F[Home View]
C --> G[Search View]
D --> H[Notifications View]
E --> I[Profile View]
D --> J[Badge: 5]
style A fill:#e6f3ff,stroke:#4a90d9,stroke-width:2px
Basic Tabbar
<div class="page" data-name="tabs">
<div class="navbar">
<div class="navbar-inner">
<div class="title">App</div>
</div>
</div>
<!-- Tabbar at the bottom -->
<div class="toolbar tabbar tabbar-labels">
<div class="toolbar-inner">
<a href="#tab-home" class="tab-link tab-link-active">
<i class="icon f7-icons">house</i>
<span class="tabbar-label">Home</span>
</a>
<a href="#tab-search" class="tab-link">
<i class="icon f7-icons">search</i>
<span class="tabbar-label">Search</span>
</a>
<a href="#tab-notifications" class="tab-link">
<i class="icon f7-icons">bell</i>
<span class="tabbar-label">Notifications</span>
<span class="badge">5</span>
</a>
<a href="#tab-profile" class="tab-link">
<i class="icon f7-icons">person</i>
<span class="tabbar-label">Profile</span>
</a>
</div>
</div>
<!-- Tab content -->
<div class="page-content">
<div class="tabs">
<div class="tab tab-active" id="tab-home">
<div class="block"><p>Home content here</p></div>
</div>
<div class="tab" id="tab-search">
<div class="block"><p>Search content here</p></div>
</div>
<div class="tab" id="tab-notifications">
<div class="block"><p>Notifications content here</p></div>
</div>
<div class="tab" id="tab-profile">
<div class="block"><p>Profile content here</p></div>
</div>
</div>
</div>
</div>
Expected output: A bottom tabbar with four tabs (Home, Search, Notifications with badge, Profile). Tapping a tab switches the visible content and highlights the active tab.
Tabbar with Views
<div id="app">
<!-- Tabbar outside pages -->
<div class="toolbar tabbar tabbar-labels">
<div class="toolbar-inner">
<a href="#view-home" class="tab-link tab-link-active">
<i class="icon f7-icons">house</i>
<span class="tabbar-label">Home</span>
</a>
<a href="#view-search" class="tab-link">
<i class="icon f7-icons">search</i>
<span class="tabbar-label">Search</span>
</a>
<a href="#view-profile" class="tab-link">
<i class="icon f7-icons">person</i>
<span class="tabbar-label">Profile</span>
</a>
</div>
</div>
<!-- Views as tabs -->
<div class="views tabs">
<div class="view tab tab-active" id="view-home">
<!-- Home view with own pages -->
</div>
<div class="view tab" id="view-search">
<!-- Search view with own pages -->
</div>
<div class="view tab" id="view-profile">
<!-- Profile view with own pages -->
</div>
</div>
</div>
var app = new Framework7({
root: '#app',
theme: 'ios',
views: [
{ el: '#view-home', routes: [{ path: '/', url: 'pages/home.html' }] },
{ el: '#view-search', routes: [{ path: '/', url: 'pages/search.html' }] },
{ el: '#view-profile', routes: [{ path: '/', url: 'pages/profile.html' }] }
]
});
Expected output: Each tab has its own independent view with its own navigation stack. Switching tabs preserves each view's state and history.
Tabbar with Icons Only
<!-- Icon-only tabbar (no labels) -->
<div class="toolbar tabbar">
<div class="toolbar-inner">
<a href="#tab1" class="tab-link tab-link-active">
<i class="icon f7-icons">house</i>
</a>
<a href="#tab2" class="tab-link">
<i class="icon f7-icons">search</i>
</a>
<a href="#tab3" class="tab-link">
<i class="icon f7-icons">bell</i>
</a>
<a href="#tab4" class="tab-link">
<i class="icon f7-icons">person</i>
</a>
</div>
</div>
<!-- Scrollable tabbar (more tabs than fit) -->
<div class="toolbar tabbar tabbar-scrollable">
<div class="toolbar-inner">
<a href="#tab1" class="tab-link tab-link-active">Tab 1</a>
<a href="#tab2" class="tab-link">Tab 2</a>
<a href="#tab3" class="tab-link">Tab 3</a>
<a href="#tab4" class="tab-link">Tab 4</a>
<a href="#tab5" class="tab-link">Tab 5</a>
<a href="#tab6" class="tab-link">Tab 6</a>
<a href="#tab7" class="tab-link">Tab 7</a>
</div>
</div>
Expected output: Icon-only tabbar saves vertical space. Scrollable tabbar allows horizontal scrolling when there are more tabs than fit on screen.
Toolbar with Buttons
<!-- Toolbar at the bottom with action buttons -->
<div class="toolbar">
<div class="toolbar-inner">
<a href="#" class="link">
<i class="icon f7-icons">trash</i>
</a>
<a href="#" class="link">
<i class="icon f7-icons">pencil</i>
</a>
<a href="#" class="link">
<i class="icon f7-icons">folder</i>
</a>
<a href="#" class="link">
<i class="icon f7-icons">ellipsis</i>
</a>
</div>
</div>
<!-- Toolbar with text buttons -->
<div class="toolbar">
<div class="toolbar-inner">
<a href="#" class="link">Edit</a>
<a href="#" class="link">Share</a>
<a href="#" class="link">Delete</a>
</div>
</div>
<!-- Toolbar with segmented control -->
<div class="toolbar">
<div class="toolbar-inner">
<div class="segmented">
<a href="#" class="button tab-link tab-link-active">Day</a>
<a href="#" class="button tab-link">Week</a>
<a href="#" class="button tab-link">Month</a>
</div>
</div>
</div>
Expected output: Toolbars can contain icon buttons, text buttons, or segmented controls. They appear at the bottom of the page by default.
Badge and Notification Management
// Update badge on a tab
var tabbar = app.tabbar.get('.tabbar');
var notifTab = tabbar.find('.tab-link').eq(2); // 3rd tab
notifTab.find('.badge').text('12');
// Or programmatically
$$('.tabbar .tab-link').eq(2).find('.badge').text('3');
// Show/hide badge
$$('.tabbar .tab-link').eq(2).find('.badge').show();
$$('.tabbar .tab-link').eq(2).find('.badge').hide();
// Update badge via F7 events
app.emit('badgeUpdate', { tab: 2, count: 7 });
// Dot indicator (no number)
$$('.tabbar .tab-link').eq(2).addClass('badge-dot');
Expected output: Badge numbers update dynamically to show notification counts. Dots indicate presence of new items without a count.
Tabbar Events
// Tab show event
$$(document).on('tab:show', '.tab', function(e) {
var tab = e.detail.tab;
console.log('Tab shown:', tab.id);
// Load data for this tab
if (tab.id === 'tab-home') {
loadHomeData();
} else if (tab.id === 'tab-notifications') {
loadNotifications();
}
});
// Tab hide event
$$(document).on('tab:hide', '.tab', function(e) {
var tab = e.detail.tab;
console.log('Tab hidden:', tab.id);
});
// Switch tab programmatically
app.tab.show('#tab-profile');
// Switch using link trigger
$$('a[href="#tab-search"]').trigger('click');
Expected output: The tab:show event fires every time a tab becomes visible, which is useful for Lazy Loading content. The tab:hide event fires when leaving a tab.
Material Tabbar
<!-- Material Design tabbar -->
<div class="toolbar tabbar tabbar-labels">
<div class="toolbar-inner">
<a href="#tab1" class="tab-link tab-link-active">
<i class="icon material-icons md-icons">home</i>
<span class="tabbar-label">Home</span>
</a>
<a href="#tab2" class="tab-link">
<i class="icon material-icons md-icons">search</i>
<span class="tabbar-label">Search</span>
</a>
<a href="#tab3" class="tab-link">
<i class="icon material-icons md-icons">notifications</i>
<span class="tabbar-label">Notifications</span>
</a>
<a href="#tab4" class="tab-link">
<i class="icon material-icons md-icons">person</i>
<span class="tabbar-label">Profile</span>
</a>
</div>
<!-- Material ripple effect indicates active tab -->
<div class="tabbar-highlight"></div>
</div>
Expected output: Material Design tabbar shows with elevation shadow, ink ripple effect on tap, and a highlighted indicator under the active tab.
Common Mistakes
Not placing tabbar inside toolbar class - Tabbar requires the
.toolbar.tabbarclasses. Using only.tabbarbreaks styling and tab switching.Missing tab-link-active on initial tab - The first tab link and its corresponding tab div both need the
tab-link-activeandtab-activeclasses respectively for correct initial state.Using non-unique tab IDs - Tab href targets (#tab-home) and tab IDs must match exactly. Duplicate IDs cause the wrong tab to activate.
Forgetting the tabbar-labels class for labeled tabs - Tab labels require the
tabbar-labelsclass on the toolbar. Without it, labels are hidden.Not using views with tabs for independent navigation - Simple tabs share the same page context. Use separate views inside tabs if each tab needs its own navigation history.
Practice Questions
- What CSS classes are required for a labeled tabbar?
- How do you add a badge to a tab link?
- How do you switch tabs programmatically?
- What is the difference between tabs with views and tabs with divs?
- How do you update a badge count dynamically?
Challenge: Build a full tabbed app with: four tabs (Home, Explore, Notifications, Profile), each tab has its own view with navigation stack, badges on Notifications tab update dynamically from a simulated data source, tab switching transitions with animation, and the active tab persists across page refreshes using localStorage.
FAQ
{{< faq "How do I change the active tab from JavaScript?" "Use app.tab.show('#tab-id') or trigger a click on the tab link: $$('a[href="#tab-id"]').trigger('click')." >}}
Mini Project
Build a social media app shell with: a bottom tabbar (Feed, Search, Post-new, Notifications, Profile), each tab is a separate view with its own pages, badge count on Notifications that increments every 30 seconds, a segmented control in the Profile toolbar (Posts, Likes, Saved), and animated tab switching.
What's Next
Tabbar provides bottom navigation. Learn how Framework7 List View creates contact lists, settings menus, and media lists with swipe actions and grouping.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro