Skip to content

Framework7 Toolbar and Tabbar — Bottom Navigation, Icons, and Badges

DodaTech Updated 2026-06-28 7 min read

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

  1. Not placing tabbar inside toolbar class - Tabbar requires the .toolbar.tabbar classes. Using only .tabbar breaks styling and tab switching.

  2. Missing tab-link-active on initial tab - The first tab link and its corresponding tab div both need the tab-link-active and tab-active classes respectively for correct initial state.

  3. Using non-unique tab IDs - Tab href targets (#tab-home) and tab IDs must match exactly. Duplicate IDs cause the wrong tab to activate.

  4. Forgetting the tabbar-labels class for labeled tabs - Tab labels require the tabbar-labels class on the toolbar. Without it, labels are hidden.

  5. 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

  1. What CSS classes are required for a labeled tabbar?
  2. How do you add a badge to a tab link?
  3. How do you switch tabs programmatically?
  4. What is the difference between tabs with views and tabs with divs?
  5. 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

Can I place a tabbar at the top of the page?

Yes. Add the class tabbar-top to the toolbar. Alternatively, use a subnavbar inside the navbar for top tab-like navigation.

How many tabs should I use?

Mobile UI guidelines recommend 3-5 tabs. Use tabbar-scrollable for 5+ tabs. Avoid more than 7 as they become hard to tap accurately.

Can I animate tab transitions?

Yes. Framework7 supports animated tab transitions. Use the tabbar-animated class or configure app.tab.showAnimation for custom animations.

{{< 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')." >}}

Do tabbars work with Framework7 React/Vue?

Yes. Framework7 React provides and components. Framework7 Vue provides f7-tabbar and f7-tab-link.

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