Tab
Tabs switch between related views in the same place on the page. They can hold icons, a dropdown or fill the full width.
Default markup
The default tabs highlight the current one. Each tab trigger points at a panel, and Bootstrap shows one panel at a time.
Home tab
Profile tab
<div class="card">
<div class="card-header">
<ul class="nav nav-tabs card-header-tabs" data-bs-toggle="tabs">
<li class="nav-item">
<a href="#tabs-home-ex1" class="nav-link active" data-bs-toggle="tab">Home</a>
</li>
<li class="nav-item">
<a href="#tabs-profile-ex1" class="nav-link" data-bs-toggle="tab">Profile</a>
</li>
</ul>
</div>
<div class="card-body">
<div class="tab-content">
<div class="tab-pane active show" id="tabs-home-ex1">
<h4>Home tab</h4>
<div>Cursus turpis vestibulum, dui in pharetra vulputate id sed non turpis ultricies fringilla at sed facilisis lacus pellentesque purus nibh</div>
</div>
<div class="tab-pane" id="tabs-profile-ex1">
<h4>Profile tab</h4>
<div>Fringilla egestas nunc quis tellus diam rhoncus ultricies tristique enim at diam, sem nunc amet, pellentesque id egestas velit sed</div>
</div>
</div>
</div>
</div>Tabs with icons
An icon in the tab label makes tabs easier to tell apart when the labels are similar.
Home tab
Profile tab
Settings tab
<div class="card">
<div class="card-header">
<ul class="nav nav-tabs card-header-tabs" data-bs-toggle="tabs">
<li class="nav-item">
<a href="#tabs-home-ex2" class="nav-link active" data-bs-toggle="tab">
<!-- Download SVG icon from http://tabler.io/icons/icon/home -->
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="icon me-2">
<path d="M5 12l-2 0l9 -9l9 9l-2 0" />
<path d="M5 12v7a2 2 0 0 0 2 2h10a2 2 0 0 0 2 -2v-7" />
<path d="M9 21v-6a2 2 0 0 1 2 -2h2a2 2 0 0 1 2 2v6" />
</svg> Home
</a>
</li>
<li class="nav-item">
<a href="#tabs-profile-ex2" class="nav-link" data-bs-toggle="tab">
<!-- Download SVG icon from http://tabler.io/icons/icon/user -->
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="icon me-2">
<path d="M8 7a4 4 0 1 0 8 0a4 4 0 0 0 -8 0" />
<path d="M6 21v-2a4 4 0 0 1 4 -4h4a4 4 0 0 1 4 4v2" />
</svg> Profile
</a>
</li>
<li class="nav-item ms-auto">
<a href="#tabs-settings-ex2" class="nav-link" title="Settings" data-bs-toggle="tab">
<svg xmlns="http://www.w3.org/2000/svg" class="icon" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path d="M10.325 4.317c.426 -1.756 2.924 -1.756 3.35 0a1.724 1.724 0 0 0 2.573 1.066c1.543 -.94 3.31 .826 2.37 2.37a1.724 1.724 0 0 0 1.065 2.572c1.756 .426 1.756 2.924 0 3.35a1.724 1.724 0 0 0 -1.066 2.573c.94 1.543 -.826 3.31 -2.37 2.37a1.724 1.724 0 0 0 -2.572 1.065c-.426 1.756 -2.924 1.756 -3.35 0a1.724 1.724 0 0 0 -2.573 -1.066c-1.543 .94 -3.31 -.826 -2.37 -2.37a1.724 1.724 0 0 0 -1.065 -2.572c-1.756 -.426 -1.756 -2.924 0 -3.35a1.724 1.724 0 0 0 1.066 -2.573c-.94 -1.543 .826 -3.31 2.37 -2.37c1 .608 2.296 .07 2.572 -1.065z" />
<circle cx="12" cy="12" r="3" />
</svg>
</a>
</li>
</ul>
</div>
<div class="card-body">
<div class="tab-content">
<div class="tab-pane active show" id="tabs-home-ex2">
<h4>Home tab</h4>
<div>Cursus turpis vestibulum, dui in pharetra vulputate id sed non turpis ultricies fringilla at sed facilisis lacus pellentesque purus nibh</div>
</div>
<div class="tab-pane" id="tabs-profile-ex2">
<h4>Profile tab</h4>
<div>Fringilla egestas nunc quis tellus diam rhoncus ultricies tristique enim at diam, sem nunc amet, pellentesque id egestas velit sed</div>
</div>
<div class="tab-pane" id="tabs-settings-ex2">
<h4>Settings tab</h4>
<div>Donec ac vitae diam amet vel leo egestas consequat rhoncus in luctus amet, facilisi sit mauris accumsan nibh habitant senectus</div>
</div>
</div>
</div>
</div>Tabs only with icons
Tabs with only an icon save space. Give each one an aria-label, because there's no text to read.
Home tab
Profile tab
Settings tab
<div class="card">
<div class="card-header">
<ul class="nav nav-tabs card-header-tabs" data-bs-toggle="tabs">
<li class="nav-item">
<a href="#tabs-home-ex3" class="nav-link active" data-bs-toggle="tab">
<!-- Download SVG icon from http://tabler.io/icons/icon/home -->
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="icon">
<path d="M5 12l-2 0l9 -9l9 9l-2 0" />
<path d="M5 12v7a2 2 0 0 0 2 2h10a2 2 0 0 0 2 -2v-7" />
<path d="M9 21v-6a2 2 0 0 1 2 -2h2a2 2 0 0 1 2 2v6" />
</svg>
</a>
</li>
<li class="nav-item">
<a href="#tabs-profile-ex3" class="nav-link" data-bs-toggle="tab">
<!-- Download SVG icon from http://tabler.io/icons/icon/user -->
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="icon">
<path d="M8 7a4 4 0 1 0 8 0a4 4 0 0 0 -8 0" />
<path d="M6 21v-2a4 4 0 0 1 4 -4h4a4 4 0 0 1 4 4v2" />
</svg>
</a>
</li>
<li class="nav-item ms-auto">
<a href="#tabs-settings-ex3" class="nav-link" title="Settings" data-bs-toggle="tab">
<!-- Download SVG icon from http://tabler.io/icons/icon/settings -->
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="icon">
<path d="M10.325 4.317c.426 -1.756 2.924 -1.756 3.35 0a1.724 1.724 0 0 0 2.573 1.066c1.543 -.94 3.31 .826 2.37 2.37a1.724 1.724 0 0 0 1.065 2.572c1.756 .426 1.756 2.924 0 3.35a1.724 1.724 0 0 0 -1.066 2.573c.94 1.543 -.826 3.31 -2.37 2.37a1.724 1.724 0 0 0 -2.572 1.065c-.426 1.756 -2.924 1.756 -3.35 0a1.724 1.724 0 0 0 -2.573 -1.066c-1.543 .94 -3.31 -.826 -2.37 -2.37a1.724 1.724 0 0 0 -1.065 -2.572c-1.756 -.426 -1.756 -2.924 0 -3.35a1.724 1.724 0 0 0 1.066 -2.573c-.94 -1.543 .826 -3.31 2.37 -2.37c1 .608 2.296 .07 2.572 -1.065" />
<path d="M9 12a3 3 0 1 0 6 0a3 3 0 0 0 -6 0" />
</svg>
</a>
</li>
</ul>
</div>
<div class="card-body">
<div class="tab-content">
<div class="tab-pane active show" id="tabs-home-ex3">
<h4>Home tab</h4>
<div>Cursus turpis vestibulum, dui in pharetra vulputate id sed non turpis ultricies fringilla at sed facilisis lacus pellentesque purus nibh</div>
</div>
<div class="tab-pane" id="tabs-profile-ex3">
<h4>Profile tab</h4>
<div>Fringilla egestas nunc quis tellus diam rhoncus ultricies tristique enim at diam, sem nunc amet, pellentesque id egestas velit sed</div>
</div>
<div class="tab-pane" id="tabs-settings-ex3">
<h4>Settings tab</h4>
<div>Donec ac vitae diam amet vel leo egestas consequat rhoncus in luctus amet, facilisi sit mauris accumsan nibh habitant senectus</div>
</div>
</div>
</div>
</div>Tabs with dropdown
A tab can open a dropdown with more views, so a long row of tabs stays short.
Home tab
Profile tab
<div class="card">
<div class="card-header">
<ul class="nav nav-tabs card-header-tabs" data-bs-toggle="tabs">
<li class="nav-item">
<a href="#tabs-home-ex4" class="nav-link active" data-bs-toggle="tab">Home</a>
</li>
<li class="nav-item">
<a href="#tabs-profile-ex4" class="nav-link" data-bs-toggle="tab">Profile</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" data-bs-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"> Dropdown </a>
<div class="dropdown-menu">
<a class="dropdown-item" href="#">Action</a>
<a class="dropdown-item" href="#">Another action</a>
</div>
</li>
</ul>
</div>
<div class="card-body">
<div class="tab-content">
<div class="tab-pane active show" id="tabs-home-ex4">
<h4>Home tab</h4>
<div>Cursus turpis vestibulum, dui in pharetra vulputate id sed non turpis ultricies fringilla at sed facilisis lacus pellentesque purus nibh</div>
</div>
<div class="tab-pane" id="tabs-profile-ex4">
<h4>Profile tab</h4>
<div>Fringilla egestas nunc quis tellus diam rhoncus ultricies tristique enim at diam, sem nunc amet, pellentesque id egestas velit sed</div>
</div>
</div>
</div>
</div>Full-width tabs
Add the .nav-fill class to make the tabs take up the full space of the parent element.
Home tab
Profile tab
Activity tab
<div class="card">
<div class="card-header">
<ul class="nav nav-tabs card-header-tabs nav-fill" data-bs-toggle="tabs">
<li class="nav-item">
<a href="#tabs-home-ex5" class="nav-link active" data-bs-toggle="tab">
<!-- Download SVG icon from http://tabler.io/icons/icon/home -->
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="icon">
<path d="M5 12l-2 0l9 -9l9 9l-2 0" />
<path d="M5 12v7a2 2 0 0 0 2 2h10a2 2 0 0 0 2 -2v-7" />
<path d="M9 21v-6a2 2 0 0 1 2 -2h2a2 2 0 0 1 2 2v6" />
</svg>
</a>
</li>
<li class="nav-item">
<a href="#tabs-profile-ex5" class="nav-link" data-bs-toggle="tab">
<!-- Download SVG icon from http://tabler.io/icons/icon/user -->
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="icon">
<path d="M8 7a4 4 0 1 0 8 0a4 4 0 0 0 -8 0" />
<path d="M6 21v-2a4 4 0 0 1 4 -4h4a4 4 0 0 1 4 4v2" />
</svg>
</a>
</li>
<li class="nav-item">
<a href="#tabs-activity-ex5" class="nav-link" data-bs-toggle="tab">
<!-- Download SVG icon from http://tabler.io/icons/icon/activity -->
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="icon">
<path d="M3 12h4l3 8l4 -16l3 8h4" />
</svg>
</a>
</li>
</ul>
</div>
<div class="card-body">
<div class="tab-content">
<div class="tab-pane active show" id="tabs-home-ex5">
<h4>Home tab</h4>
<div>Cursus turpis vestibulum, dui in pharetra vulputate id sed non turpis ultricies fringilla at sed facilisis lacus pellentesque purus nibh</div>
</div>
<div class="tab-pane" id="tabs-profile-ex5">
<h4>Profile tab</h4>
<div>Fringilla egestas nunc quis tellus diam rhoncus ultricies tristique enim at diam, sem nunc amet, pellentesque id egestas velit sed</div>
</div>
<div class="tab-pane" id="tabs-activity-ex5">
<h4>Activity tab</h4>
<div>Donec ac vitae diam amet vel leo egestas consequat rhoncus in luctus amet, facilisi sit mauris accumsan nibh habitant senectus</div>
</div>
</div>
</div>
</div>JavaScript
Tabler activates the tab that matches the URL hash on page load, so you can link to a specific tab. This is the code that runs:
export const EnableActivationTabsFromLocationHash = (): void => {
const locationHash: string = window.location.hash
if (!locationHash) {
return
}
for (const tab of document.querySelectorAll<HTMLAnchorElement>('[data-bs-toggle="tab"], [data-tblr-toggle="tab"]')) {
if (tab.hash !== locationHash) {
continue
}
// A tab link outside a .nav/.list-group has no parent to switch in;
// show() would throw and stop the rest of the bundle.
try {
;(Tab.getOrCreateInstance(tab) as InstanceType<typeof Tab>).show()
} catch (error) {
console.error(error)
}
}
}
onDOMContentLoaded(EnableActivationTabsFromLocationHash)This runs on DOMContentLoaded, so show.bs.tab and shown.bs.tab for the hash tab fire before any script that itself waits for DOMContentLoaded. Add the listener earlier (a plain <script>, not one that is deferred or waits for the load event), or read Tab.getInstance(triggerEl) after DOMContentLoaded to find the tab that was activated.
Accessibility
- Wrap the tabs in an element with
role="tablist", give each triggerrole="tab"and each panelrole="tabpanel", and link them witharia-controlsandaria-labelledby. - Bootstrap sets
aria-selectedand moves focus with the arrow keys, but only when the roles above are present. Without them the tabs are plain links. - Tabler activates a tab from the url hash on page load, so a tab trigger with
href="#billing"doubles as a deep link. Keep the panel ids stable if you link to them. - Only the active panel should be reachable. Bootstrap hides the others with
display: none, which also removes them from the tab order.
Class reference
Every class this component ships, grouped by what it changes. A name in braces stands for a family — {color} is any base color, {breakpoint} any responsive step.
nav-tabs | component | Applied with nav, styles the triggers as tabs |
nav-link | part | One tab trigger; needs role="tab" and aria-controls |
tab-content | part | Wrapper around the panels |
tab-pane | part | One panel; needs role="tabpanel" |
nav-underline | style | Underline marker instead of a filled tab |
nav-bordered | style | Bordered tab style |
nav-fill | modifier | Spreads the tabs across the full width |
CSS
Variables
The component uses local CSS variables
on .nav-tabs for real-time customization. Values for the CSS variables are set via Sass, so Sass customization is still supported, too. Source: core/scss/bootstrap/_nav.scss.
--nav-tabs-border-width: #{$nav-tabs-border-width};
--nav-tabs-border-color: #{$nav-tabs-border-color};
--nav-tabs-border-radius: #{$nav-tabs-border-radius};
--nav-tabs-link-hover-border-color: #{$nav-tabs-link-hover-border-color};
--nav-tabs-link-active-color: #{$nav-tabs-link-active-color};
--nav-tabs-link-active-bg: #{$nav-tabs-link-active-bg};
--nav-tabs-link-active-border-color: #{$nav-tabs-link-active-border-color};Sass variables
Override these variables before importing Tabler to change the defaults. Source: core/scss/_variables.scss.
$nav-link-padding-y: 0.5rem;
$nav-link-padding-x: 0.75rem;
$nav-link-font-size: var(--body-font-size);
$nav-link-font-weight: null;
$nav-link-color: var(--secondary-color);
$nav-link-active-color: var(--body-color);
$nav-link-hover-color: var(--link-hover-color);
$nav-link-transition:
color 0.15s ease-in-out,
background-color 0.15s ease-in-out,
border-color 0.15s ease-in-out,
$focus-ring-transition;
$nav-link-disabled-color: var(--disabled-color);
$nav-link-icon-size: $icon-size;
$nav-link-icon-color: color-transparent(var(--nav-link-color), 0.5);
$nav-link-hover-icon-color: color-transparent(var(--nav-link-color), 0.8);
$nav-pills-border-radius: var(--border-radius);
$nav-pills-link-active-color: var(--primary);
$nav-pills-link-active-bg: var(--active-bg);
$nav-bordered-border-color: var(--border-color);
$nav-bordered-border-width: var(--border-width);
$nav-bordered-link-active-color: var(--primary);
$nav-bordered-link-active-border-color: var(--primary);
$nav-bordered-link-active-border-width: 2 * $border-width;
$nav-bordered-margin-x: 1.25rem;
$nav-tabs-border-color: var(--border-color);
$nav-tabs-border-width: var(--border-width);
$nav-tabs-border-radius: var(--border-radius);
$nav-tabs-link-hover-border-color: $nav-tabs-border-color $nav-tabs-border-color $nav-tabs-border-color;
$nav-tabs-link-active-color: var(--body-color);
$nav-tabs-link-active-bg: var(--body-bg);
$nav-tabs-link-active-border-color: $nav-tabs-link-hover-border-color;
$nav-underline-gap: 1rem;
$nav-underline-border-width: 0.125rem;
$nav-underline-link-active-color: var(--emphasis-color);
$nav-vertical-nested-margin-start: 1.25rem;
$nav-vertical-nested-padding-start: 0.5rem;
$nav-link-toggle-padding-x: 0.25rem;
$nav-link-icon-margin-end: 0.5rem;
