Bootstrap 5 Nav Tabs
Bootstrap 5 Nav Tabs transform a standard navigation list into a tabbed interface that shows and hides associated content panels without a page reload. They use the .nav-tabs modifier on the .nav base class, combined with the Tab JavaScript plugin to manage active states and panel visibility. Use them when you need to present distinct but related content sections (such as product specs, account settings, or dashboard views) within a single contained area.
Bootstrap class
.nav-tabsCommon use cases
- Product detail pages that separate Description, Specifications, Reviews, and Shipping Info into tabs to reduce page length without sacrificing content depth
- SaaS account settings pages where Profile, Security, Billing, and Notifications each occupy a dedicated tab panel
- Developer documentation portals that show code examples in multiple languages (JavaScript, Python, cURL) using tabs to avoid vertical scrolling through all variants
- Analytics dashboards that segment data views (such as Daily, Weekly, and Monthly summaries) into tabs sharing the same chart container
Variants and classes
| Variant | Description and classes |
|---|---|
| Basic tabs | Tab-styled links with an active state.nav nav-tabs + nav-link active |
| Tabs with panes | Tabs that switch content without a page load.nav-link + data-bs-toggle="tab" + tab-content + tab-pane fade |
| Fill and justify | Tabs share the full width of the row.nav nav-tabs nav-fill / nav-justified |
| Tab with dropdown | One tab opens a dropdown of more options.nav-item dropdown + dropdown-menu |
Code example
<ul class="nav nav-tabs" id="projectTabs" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link active" id="overview-tab" data-bs-toggle="tab" data-bs-target="#overview" type="button" role="tab" aria-controls="overview" aria-selected="true">Overview</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="timeline-tab" data-bs-toggle="tab" data-bs-target="#timeline" type="button" role="tab" aria-controls="timeline" aria-selected="false">Timeline</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="files-tab" data-bs-toggle="tab" data-bs-target="#files" type="button" role="tab" aria-controls="files" aria-selected="false">Files</button>
</li>
</ul>
<div class="tab-content" id="projectTabsContent">
<div class="tab-pane fade show active" id="overview" role="tabpanel" aria-labelledby="overview-tab">
<p class="mt-3">Project overview: goals, stakeholders, and current status summary.</p>
</div>
<div class="tab-pane fade" id="timeline" role="tabpanel" aria-labelledby="timeline-tab">
<p class="mt-3">Milestone schedule and upcoming deadlines for Q3 delivery.</p>
</div>
<div class="tab-pane fade" id="files" role="tabpanel" aria-labelledby="files-tab">
<p class="mt-3">Uploaded assets, design files, and shared documents.</p>
</div>
</div>Live examples
Basic Nav Tabs
Canvas template variants
Canvas Builder builds pages on the Canvas HTML template, which adds its own styled versions of Bootstrap 5 components. Variants you can ask for in a prompt:
- Canvas Builder generated nav tabs with custom colours
- Nav Tabs with interactive states
- Responsive nav tabs for all screen sizes
Best practices
Always use <button> elements, not <a> tags, for tab triggers
Bootstrap 5 recommends <button> with data-bs-toggle="tab" and data-bs-target instead of anchor href linking. This avoids hash-based URL changes that break browser history and screen reader announcements.
Add the fade class to tab panes for a smoother transition
Pairing tab-pane fade with show active on the default pane enables a CSS opacity transition when switching tabs. Without it, panels swap instantly with no visual feedback, which can feel abrupt on content-heavy interfaces.
Persist the active tab across page reloads using localStorage
Listen for Bootstrap's shown.bs.tab event, store event.target.id in localStorage, then on page load query that ID and trigger .show() on the matching Tab instance to restore the user's last position.
Use nav-fill or nav-justified for equal-width tabs
Adding .nav-fill makes each tab item take proportional space based on its label length; .nav-justified forces every tab to equal width regardless of content. Useful when you have exactly 3 to 4 short labels and want a balanced, symmetric header.
FAQ
How do I activate a specific tab programmatically on page load?
const triggerEl = document.querySelector('#your-tab-id'); bootstrap.Tab.getInstance(triggerEl)?.show();, or create a new instance with new bootstrap.Tab(triggerEl).show() if it hasn't been initialised yet. This is the reliable approach for deep-linking to a tab based on a URL parameter or stored user preference.How do I style the active tab with a custom brand colour instead of Bootstrap's default blue border?
.nav-tabs .nav-link.active { color: #your-color; border-color: #your-color #your-color #fff; } and .nav-tabs { border-bottom-color: #your-color; }. If you're using Bootstrap's Sass source, set $nav-tabs-link-active-color and $nav-tabs-link-active-border-color before importing Bootstrap to keep overrides clean and maintainable.How does Canvas Builder handle Nav Tabs generation?
data-bs- attributes pre-connected, no manual ID matching required. It applies your project's brand colours to the active tab indicator automatically and outputs responsive markup that stacks or scrolls horizontally on small screens based on the layout context you describe.