Pills
Bootstrap 5 Pills component
Pills are quasi-navigation components which can highly improve website clarity and increase user experience.
Note: Read the API tab to find all available options and advanced customization
Basic example
Basic pills are divided into 2 main sections -
Pills navs (containing nav-item
s) and
Pills content (containing tab-pane
s).
Use id
and href
attribute to connect pills navs with pills content.
In the example below Tab 1 uses href="#ex1-pills-1"
in the first
nav-link
element to connect it with the first tab-pane
which has an
ID ex1-pills-1
.
<!-- Pills navs -->
<ul class="nav nav-pills mb-3" id="ex1" role="tablist">
<li class="nav-item" role="presentation">
<a
class="nav-link active"
id="ex1-tab-1"
data-mdb-toggle="pill"
href="#ex1-pills-1"
role="tab"
aria-controls="ex1-pills-1"
aria-selected="true"
>Tab 1</a
>
</li>
<li class="nav-item" role="presentation">
<a
class="nav-link"
id="ex1-tab-2"
data-mdb-toggle="pill"
href="#ex1-pills-2"
role="tab"
aria-controls="ex1-pills-2"
aria-selected="false"
>Tab 2</a
>
</li>
<li class="nav-item" role="presentation">
<a
class="nav-link"
id="ex1-tab-3"
data-mdb-toggle="pill"
href="#ex1-pills-3"
role="tab"
aria-controls="ex1-pills-3"
aria-selected="false"
>Tab 3</a
>
</li>
</ul>
<!-- Pills navs -->
<!-- Pills content -->
<div class="tab-content" id="ex1-content">
<div
class="tab-pane fade show active"
id="ex1-pills-1"
role="tabpanel"
aria-labelledby="ex1-tab-1"
>
Tab 1 content
</div>
<div class="tab-pane fade" id="ex1-pills-2" role="tabpanel" aria-labelledby="ex1-tab-2">
Tab 2 content
</div>
<div class="tab-pane fade" id="ex1-pills-3" role="tabpanel" aria-labelledby="ex1-tab-3">
Tab 3 content
</div>
</div>
<!-- Pills content -->
Fill and justify
Force your .nav
's contents to extend the full available width one of two modifier
classes.
Fill
To proportionately fill all available space with your .nav-item
s, use
.nav-fill
. Notice that all horizontal space is occupied, but not every nav item
has the same width.
<!-- Pills navs -->
<ul class="nav nav-pills nav-fill mb-3" id="ex1" role="tablist">
<li class="nav-item" role="presentation">
<a
class="nav-link active"
id="ex2-tab-1"
data-mdb-toggle="pill"
href="#ex2-pills-1"
role="tab"
aria-controls="ex2-pills-1"
aria-selected="true"
>Link</a
>
</li>
<li class="nav-item" role="presentation">
<a
class="nav-link"
id="ex2-tab-2"
data-mdb-toggle="pill"
href="#ex2-pills-2"
role="tab"
aria-controls="ex2-pills-2"
aria-selected="false"
>Very very very very long link</a
>
</li>
<li class="nav-item" role="presentation">
<a
class="nav-link"
id="ex2-tab-3"
data-mdb-toggle="pill"
href="#ex2-pills-3"
role="tab"
aria-controls="ex2-pills-3"
aria-selected="false"
>Another link</a
>
</li>
</ul>
<!-- Pills navs -->
<!-- Pills content -->
<div class="tab-content" id="ex2-content">
<div
class="tab-pane fade show active"
id="ex2-pills-1"
role="tabpanel"
aria-labelledby="ex2-tab-1"
>
Tab 1 content
</div>
<div
class="tab-pane fade"
id="ex2-pills-2"
role="tabpanel"
aria-labelledby="ex2-tab-2"
>
Tab 2 content
</div>
<div
class="tab-pane fade"
id="ex2-pills-3"
role="tabpanel"
aria-labelledby="ex2-tab-3"
>
Tab 3 content
</div>
</div>
<!-- Pills content -->
Justify
For equal-width elements, use .nav-justified
. All horizontal space will be
occupied by nav links, but unlike the .nav-fill
above, every nav item will be
the same width.
<!-- Pills navs -->
<ul class="nav nav-pills nav-justified mb-3" id="ex1" role="tablist">
<li class="nav-item" role="presentation">
<a
class="nav-link active"
id="ex3-tab-1"
data-mdb-toggle="pill"
href="#ex3-pills-1"
role="tab"
aria-controls="ex3-pills-1"
aria-selected="true"
>Link</a
>
</li>
<li class="nav-item" role="presentation">
<a
class="nav-link"
id="ex3-tab-2"
data-mdb-toggle="pill"
href="#ex3-pills-2"
role="tab"
aria-controls="ex3-pills-2"
aria-selected="false"
>Very very very very long link</a
>
</li>
<li class="nav-item" role="presentation">
<a
class="nav-link"
id="ex3-tab-3"
data-mdb-toggle="pill"
href="#ex3-pills-3"
role="tab"
aria-controls="ex3-pills-3"
aria-selected="false"
>Another link</a
>
</li>
</ul>
<!-- Pills navs -->
<!-- Pills content -->
<div class="tab-content" id="ex2-content">
<div
class="tab-pane fade show active"
id="ex3-pills-1"
role="tabpanel"
aria-labelledby="ex3-tab-1"
>
Tab 1 content
</div>
<div
class="tab-pane fade"
id="ex3-pills-2"
role="tabpanel"
aria-labelledby="ex3-tab-2"
>
Tab 2 content
</div>
<div
class="tab-pane fade"
id="ex3-pills-3"
role="tabpanel"
aria-labelledby="ex3-tab-3"
>
Tab 3 content
</div>
</div>
<!-- Pills content -->
Vertical
Stack your navigation by changing the flex item direction with the
.flex-column
utility. Need to stack them on some viewports but not others? Use
the responsive versions (e.g., .flex-sm-column
).
For proper layout, you may also need to use grid to adjust navs and content.
<div class="row">
<div class="col-3">
<!-- Tab navs -->
<div
class="nav flex-column nav-pills text-center"
id="v-pills-tab"
role="tablist"
aria-orientation="vertical"
>
<a
class="nav-link active"
id="v-pills-home-tab"
data-mdb-toggle="pill"
href="#v-pills-home"
role="tab"
aria-controls="v-pills-home"
aria-selected="true"
>Home</a
>
<a
class="nav-link"
id="v-pills-profile-tab"
data-mdb-toggle="pill"
href="#v-pills-profile"
role="tab"
aria-controls="v-pills-profile"
aria-selected="false"
>Profile</a
>
<a
class="nav-link"
id="v-pills-messages-tab"
data-mdb-toggle="pill"
href="#v-pills-messages"
role="tab"
aria-controls="v-pills-messages"
aria-selected="false"
>Messages</a
>
</div>
<!-- Tab navs -->
</div>
<div class="col-9">
<!-- Tab content -->
<div class="tab-content" id="v-pills-tabContent">
<div
class="tab-pane fade show active"
id="v-pills-home"
role="tabpanel"
aria-labelledby="v-pills-home-tab"
>
Home content
</div>
<div
class="tab-pane fade"
id="v-pills-profile"
role="tabpanel"
aria-labelledby="v-pills-profile-tab"
>
Profile content
</div>
<div
class="tab-pane fade"
id="v-pills-messages"
role="tabpanel"
aria-labelledby="v-pills-messages-tab"
>
Messages content
</div>
</div>
<!-- Tab content -->
</div>
</div>
If you want to support our friends from Tailwind Elements you can also check out the Tailwind pills documentation.
Pills - API
Usage
Regarding accessibility
If you’re using navs to provide a navigation bar, be sure to add a
role="navigation"
to the most logical parent container of the
<ul>
, or wrap a <nav>
element around the whole
navigation. Do not add the role to the <ul>
itself, as this would prevent
it from being announced as an actual list by assistive technologies.
Note that navigation bars, even if visually styled as pills with the
.nav-pills
class, should not be given
role="tablist"
, role="tab"
or
role="tabpanel"
attributes. These are only appropriate for dynamic tabbed
interfaces, as described in the
WAI
ARIA Authoring Practices. The aria-current
attribute is not necessary on dynamic tabbed interfaces since
our JavaScript handles the selected state by adding aria-selected="true"
on the
active tab.
Via data attributes
You can activate a tab or pill navigation without writing any JavaScript by simply specifying
data-mdb-toggle="tab"
or data-mdb-toggle="pill"
on an element. Use
these data attributes on .nav-pills
or .nav-pills
.
<!-- Nav pills -->
<ul class="nav nav-pills" id="myTab" role="tablist">
<li class="nav-item" role="presentation">
<a
class="nav-link active"
id="home-tab"
data-mdb-toggle="tab"
href="#home"
role="tab"
aria-controls="home"
aria-selected="true"
>Home</a
>
</li>
<li class="nav-item" role="presentation">
<a
class="nav-link"
id="profile-tab"
data-mdb-toggle="tab"
href="#profile"
role="tab"
aria-controls="profile"
aria-selected="false"
>Profile</a
>
</li>
<li class="nav-item" role="presentation">
<a
class="nav-link"
id="messages-tab"
data-mdb-toggle="tab"
href="#messages"
role="tab"
aria-controls="messages"
aria-selected="false"
>Messages</a
>
</li>
<li class="nav-item" role="presentation">
<a
class="nav-link"
id="settings-tab"
data-mdb-toggle="tab"
href="#settings"
role="tab"
aria-controls="settings"
aria-selected="false"
>Settings</a
>
</li>
</ul>
<!-- Tab panes -->
<div class="tab-content">
<div class="tab-pane active" id="home" role="tabpanel" aria-labelledby="home-tab">
...
</div>
<div class="tab-pane" id="profile" role="tabpanel" aria-labelledby="profile-tab">
...
</div>
<div class="tab-pane" id="messages" role="tabpanel" aria-labelledby="messages-tab">
...
</div>
<div class="tab-pane" id="settings" role="tabpanel" aria-labelledby="settings-tab">
...
</div>
</div>
Via JavaScript
Enable tabbable pills via JavaScript (each tab needs to be activated individually):
const triggerTabList = [].slice.call(document.querySelectorAll('#myTab a'))
triggerTabList.forEach((triggerEl) => {
const tabTrigger = new mdb.Tab(triggerEl)
triggerEl.addEventListener('click', (e) => {
e.preventDefault()
tabTrigger.show()
})
})
You can activate individual pills in several ways:
const triggerEl = document.querySelector('#myTab a[href="#profile"]')
mdb.Tab.getInstance(triggerEl).show() // Select tab by name
const triggerFirstTabEl = document.querySelector('#myTab li:first-child a')
mdb.Tab.getInstance(triggerFirstTabEl).show() // Select first tab
Via jQuery
Note: By default, MDB does not include jQuery and you have to add it to the project on your own.
$('.example-class').tab();
Methods
Asynchronous methods and transitions:
All API methods are asynchronous and start a transition.
They return to the caller as soon as the transition is started but
before it ends. In addition, a method call on a
transitioning component will be ignored.
Name | Description | Example |
---|---|---|
show |
Selects the given tab and shows its associated pane. Any other tab that was previously selected becomes unselected and its associated pane is hidden. Returns to the caller before the tab pane has actually been shown (i.e. before the shown.mdb.tab event occurs). | instance.show() |
dispose |
Destroys an element’s tab. | instance.dispose() |
getInstance |
Static method which allows you to get the tab instance associated to a DOM element. | Tab.getInstance(someTabTriggerEl) |
const someTabTriggerEl = document.querySelector('#someTabTrigger')
const tab = new mdb.Tab(someTabTriggerEl) tab.show()
Events
When showing a new tab, the events fire in the following order:
hide.mdb.tab
(on the current active tab)show.mdb.tab
(on the to-be-shown tab)-
hidden.mdb.tab
(on the previous active tab, the same one as for thehide.mdb.tab
event) -
shown.mdb.tab
(on the newly-active just-shown tab, the same one as for theshow.mdb.tab
event)
If no tab was already active, then the hide.mdb.tab
and
hidden.mdb.tab
events will not be fired.
Event type | Description |
---|---|
show.mdb.tab |
This event fires on tab show, but before the new tab has been shown. Use
event.target and event.relatedTarget to target the active tab
and the previous active tab (if available) respectively.
|
shown.mdb.tab |
This event fires on tab show after a tab has been shown. Use
event.target and event.relatedTarget to target the active tab
and the previous active tab (if available) respectively.
|
hide.mdb.tab |
This event fires when a new tab is to be shown (and thus the previous active tab is to
be hidden). Use event.target and event.relatedTarget to target
the current active tab and the new soon-to-be-active tab, respectively.
|
hidden.mdb.tab |
This event fires after a new tab is shown (and thus the previous active tab is hidden).
Use event.target and event.relatedTarget to target the
previous active tab and the new active tab, respectively.
|
const tabEl = document.querySelector('a[data-mdb-toggle="tab"]')
tabEl.addEventListener('shown.mdb.tab', (e) => {
e.target // newly activated tab
e.relatedTarget // previous active tab
})
Import
MDB UI KIT also works with module bundlers. Use the following code to import this component:
import { Tab } from 'mdb-ui-kit';