jQuery plugin for making Bootstrap 3 Tabs scroll horizontally rather than wrap.
Here's what they look like:
And here are plunks showing them working with:
There are also optional features available:
- Download it or install it using bower:
bower install jquery-bootstrap-scrolling-tabs
or npm:npm install jquery-bootstrap-scrolling-tabs
- Include
jquery.scrolling-tabs.min.css
(orjquery.scrolling-tabs.css
) on your page after Bootstrap's CSS - Include
jquery.scrolling-tabs.min.js
(orjquery.scrolling-tabs.js
) on your page (make sure that jQuery is included before it, of course)
If you're using Bootstrap Tabs (nav-tabs
) and you don't want them to wrap if the page is too narrow to accommodate them all in one row, you can use this plugin to keep them in a row that scrolls horizontally without a scrollbar.
It adjusts itself on window resize (debounced to prevent resize event wackiness), so if the window is widened enough to accommodate all tabs, scrolling will deactivate and the scroll arrows will disappear. (And, of course, vice versa if the window is narrowed.)
If your nav-tabs
markup looks like this:
<!-- Nav tabs -->
<ul class="nav nav-tabs" role="tablist">
<li role="presentation" class="active"><a href="#tab1" role="tab" data-toggle="tab">Tab Number 1</a></li>
<li role="presentation"><a href="#tab2" role="tab" data-toggle="tab">Tab Number 2</a></li>
<li role="presentation"><a href="#tab3" role="tab" data-toggle="tab">Tab Number 3</a></li>
<li role="presentation"><a href="#tab4" role="tab" data-toggle="tab">Tab Number 4</a></li>
<li role="presentation"><a href="#tab5" role="tab" data-toggle="tab">Tab Number 5</a></li>
</ul>
<!-- Tab panes -->
<div class="tab-content">
<div role="tabpanel" class="tab-pane active" id="tab1">Tab 1 content...</div>
<div role="tabpanel" class="tab-pane" id="tab2">Tab 2 content...</div>
<div role="tabpanel" class="tab-pane" id="tab3">Tab 3 content...</div>
<div role="tabpanel" class="tab-pane" id="tab4">Tab 4 content...</div>
<div role="tabpanel" class="tab-pane" id="tab5">Tab 5 content...</div>
</div>
you can wrap the tabs in the scroller like this:
$('.nav-tabs').scrollingTabs();
You can also pass in the scrollToTabEdge
option:
$('.nav-tabs').scrollingTabs({
scrollToTabEdge: true
});
This will force the scrolling to always end with a tab edge aligned with the left scroll arrow. More details here.
You can also pass in the disableScrollArrowsOnFullyScrolled
option:
$('.nav-tabs').scrollingTabs({
disableScrollArrowsOnFullyScrolled: true
});
This will cause the left scroll arrow to disable when the tabs are scrolled fully left, and the right scroll arrow to disable when the tabs are scrolled fully right.
To prevent a flash of the tabs on page load/refresh before they get wrapped
inside the scroller, you can hide your .nav-tabs
and .tab-content
with
some CSS (display: none
).
The plugin will automatically unhide the .nav-tabs
when they're ready,
and you can hook into the ready.scrtabs
event (which gets fired when
the tabs are ready) to unhide your .tab-content
:
$('.nav-tabs')
.scrollingTabs()
.on('ready.scrtabs', function() {
$('.tab-content').show();
});
The scrolling container should automatically refresh itself on window resize, but to manually force a refresh you can call the plugin's refresh
method:
$('.nav-tabs').scrollingTabs('refresh');
On window resize, the scrolling container should automatically scroll to the active tab if it's offscreen, but you can also programmatically force a scroll to the active tab any time (if, for example, you're programmatically setting the active tab) by calling the plugin's scrollToActiveTab
method:
$('.nav-tabs').scrollingTabs('scrollToActiveTab');
If your tabs are data-driven rather than defined in your markup, you just need to pass your tabs array to the plugin and it will generate the tab elements for you.
So your tabs data should look something like this (note that the tab titles can contain HTML):
var myTabs = [
{ paneId: 'tab01', title: 'Tab <em>1</em> of 12', content: 'Tab Number 1 Content', active: true, disabled: false },
{ paneId: 'tab02', title: 'Tab 2 of 12', content: 'Tab Number 2 Content', active: false, disabled: false },
{ paneId: 'tab03', title: 'Tab 3 of 12', content: 'Tab Number 3 Content', active: false, disabled: false },
{ paneId: 'tab04', title: 'Tab 4 of 12', content: 'Tab Number 4 Content', active: false, disabled: false },
{ paneId: 'tab05', title: 'Tab 5 of 12', content: 'Tab Number 5 Content', active: false, disabled: false }
];
You would then need a target element to append the tabs and panes to, like this:
<!-- build .nav-tabs and .tab-content in here -->
<div id="tabs-inside-here"></div>
Then just call the plugin on that element, passing a settings object with a tabs
property pointing to your tabs array:
$('#tabs-inside-here').scrollingTabs({
tabs: myTabs
});
Each tab object in the array must have a property for
- the tab title (text or HTML)
- the ID of its target pane (text)
- its active state (bool)
Optionally, it can also have a boolean for its disabled
state.
If you want the plugin to generate the tab panes also, include a content
property on the tab objects.
If your tab objects have a content
property but you don't want the plugin to generate the panes, pass in plugin option ignoreTabPanes: true
when calling the plugin.
$('#tabs-inside-here').scrollingTabs({
tabs: myTabs,
ignoreTabPanes: true
});
By default, the plugin assumes those properties will be named title
, paneId
, active
, disabled
, and content
, but if you want to use different property names, you can pass your property names in as properties on the settings object:
$('#tabs-inside-here').scrollingTabs({
tabs: myTabs, // required,
propTitle: 'myTitle', // required if not 'title'
propPaneId: 'myPaneId', // required if not 'paneId'
propActive: 'myActive', // required if not 'active'
propDisabled: 'myDisabled', // required if not 'disabled'
propContent: 'myContent' // required if not 'content'
});
```javascript
So, for example, if your tab objects used the property name `label` for their titles instead of `title`, you would need to pass property `propTitle: 'label'` in your settings object.
```javascript
$('#tabs-inside-here').scrollingTabs({
tabs: myTabs,
propTitle: 'label'
});
And just like in Use Case #1, you can also pass in the scrollToTabEdge
option if you want to force the scrolling to always end with a tab edge aligned with the left scroll arrow:
$('#tabs-inside-here').scrollingTabs({
tabs: myTabs,
scrollToTabEdge: true
});
You can also pass in the disableScrollArrowsOnFullyScrolled
option if you want the scroll arrow to disable when the tabs are fully scrolled in that direction:
$('#tabs-inside-here').scrollingTabs({
tabs: myTabs,
disableScrollArrowsOnFullyScrolled: true
});
On tabs
data change, just call the plugin's refresh
method to refresh the tabs on the page:
$('#tabs-inside-here').scrollingTabs('refresh');
On tabs
data change, if you want the active tab to be set based on the updated tabs data (i.e., you want to override the current active tab setting selected by the user), for example, if you added a new tab and you want it to be the active tab, pass the forceActiveTab
flag on refresh:
$('#tabs-inside-here').scrollingTabs('refresh', {
forceActiveTab: true
});
If you want to ensure the scrolling always ends with a tab edge aligned with the left scroll arrow so there won't be a partially hidden tab, pass in option scrollToTabEdge: true
:
$('#tabs-inside-here').scrollingTabs({
tabs: myTabs,
scrollToTabEdge: true
});
There's no way to guarantee the left and right edges will be full tabs because that's dependent on the the width of the tabs and the window. So this just makes sure the left side will be a full tab.
If you want the left scroll arrow to disable when the tabs are scrolled fully left, and the right scroll arrow to disable when the tabs are scrolled fully right, pass in option disableScrollArrowsOnFullyScrolled: true
:
$('#tabs-inside-here').scrollingTabs({
tabs: myTabs,
disableScrollArrowsOnFullyScrolled: true
});
Any options that can be passed into the plugin can also be set on the plugin's defaults
object:
$.fn.scrollingTabs.defaults.tabs = myTabs;
$.fn.scrollingTabs.defaults.forceActiveTab = true;
$.fn.scrollingTabs.defaults.scrollToTabEdge = true;
$.fn.scrollingTabs.defaults.disableScrollArrowsOnFullyScrolled = true;
The plugin triggers event ready.scrtabs
when the tabs have been wrapped in
the scroller and are ready for viewing:
$('.nav-tabs')
.scrollingTabs()
.on('ready.scrtabs', function() {
// tabs ready, do my other stuff...
});
$('#tabs-inside-here')
.scrollingTabs({ tabs: tabs })
.on('ready.scrtabs', function() {
// tabs ready, do my other stuff...
});
To destroy the plugin, call its destroy
method:
$('#tabs-inside-here').scrollingTabs('destroy');
If you were wrapping markup, the markup will be restored; if your tabs were data-driven, the tabs will be destroyed along with the plugin.
MIT License.