HTML
<div class="mb-3 text-center p-5">
<h1>Tabs Responsive with Bootstrap 4</h1>
<p>
Try to hack Bootstrap 4 nav-tabs component for REALLY really simple in visual when view in mobile size.<br/>
<span class="small">In fact, I just too lazy to deal it with complicate function and code</span>
</p>
<p class="font-italic">- Try to resize window and see what's happend. -</p>
</div>
<!-- Start Tabs -->
<div class="nav-tabs-wrapper">
<ul class="nav nav-tabs dragscroll horizontal">
<li class="nav-item"><a class="nav-link active" data-toggle="tab" href="#tabA">Tab A</a></li>
<li class="nav-item"><a class="nav-link" data-toggle="tab" href="#tabB">Tab B long</a></li>
<li class="nav-item"><a class="nav-link" data-toggle="tab" href="#tabC">Tab C loooonggggg</a></li>
<li class="nav-item"><a class="nav-link" data-toggle="tab" href="#tabD">Tab D looooongggg too</a></li>
<li class="nav-item"><a class="nav-link" data-toggle="tab" href="#tabE">Tab E</a></li>
</ul>
</div>
<span class="nav-tabs-wrapper-border" role="presentation"></span>
<div class="tab-content">
<div class="tab-pane fade show active" id="tabA">
<p>This is tab A</p>
</div>
<div class="tab-pane fade" id="tabB">
<p>This is tab B</p>
</div>
<div class="tab-pane fade" id="tabC">
<p>and C</p>
</div>
<div class="tab-pane fade" id="tabD">
<p>...D</p>
</div>
<div class="tab-pane fade" id="tabE">
<p>Okay, last one E</p>
</div>
</div>
<!-- End Tabs -->
<div class="mt-5">
<div class="container">
<h2 class="h5">Dependencies</h2>
<ul>
<li>jQuery 3</li>
<li>Bootstrap 4 beta</li>
<li>Dragscroll (This use for dragable tabs with mouse)</li>
</ul>
<h2 class="h5">Warning</h2>
<ul>
<li>Do not work when justify tabs to center but you can try CSS @media-query justify tabs when all tabs show already.</li>
<li>Tested on Windows and Android but not on Mac OSX or iOS</li>
</ul>
</div>
</div>
SCSS
.nav-tabs-wrapper {
display: block;
overflow: hidden;
height: calc(1.5rem + 1rem + 2px); /** 1.5 is font-size, 1 is padding top and bottom, 2 is border width top and bottom */
position: relative;
z-index: 1;
margin-bottom: -1px;
.nav-tabs {
overflow-x: auto;
flex-wrap: nowrap;
border-bottom: 0;
}
.nav-item {
margin-bottom: 0;
&:first-child {
padding-left: 15px;
}
&:last-child {
padding-right: 15px;
}
}
.nav-link {
white-space: nowrap;
}
.dragscroll:active,
.dragscroll:active a {
cursor: -webkit-grabbing;
}
}
.nav-tabs-wrapper-border {
display: block;
width: 100%;
border-top: 1px solid #ddd;
}
.tab-pane {
padding: 1rem;
}
body {
color: #555;
}
JAVASCRIPT
/**
* @fileoverview dragscroll - scroll area by dragging
* @version 0.0.8
*
* @license MIT, see http://github.com/asvd/dragscroll
* @copyright 2015 asvd <heliosframework@gmail.com>
*/
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
define(['exports'], factory);
} else if (typeof exports !== 'undefined') {
factory(exports);
} else {
factory((root.dragscroll = {}));
}
}(this, function (exports) {
var _window = window;
var _document = document;
var mousemove = 'mousemove';
var mouseup = 'mouseup';
var mousedown = 'mousedown';
var EventListener = 'EventListener';
var addEventListener = 'add'+EventListener;
var removeEventListener = 'remove'+EventListener;
var newScrollX, newScrollY;
var dragged = [];
var reset = function(i, el) {
for (i = 0; i < dragged.length;) {
el = dragged[i++];
el = el.container || el;
el[removeEventListener](mousedown, el.md, 0);
_window[removeEventListener](mouseup, el.mu, 0);
_window[removeEventListener](mousemove, el.mm, 0);
}
// cloning into array since HTMLCollection is updated dynamically
dragged = [].slice.call(_document.getElementsByClassName('dragscroll'));
for (i = 0; i < dragged.length;) {
(function(el, lastClientX, lastClientY, pushed, scroller, cont){
(cont = el.container || el)[addEventListener](
mousedown,
cont.md = function(e) {
if (!el.hasAttribute('nochilddrag') ||
_document.elementFromPoint(
e.pageX, e.pageY
) == cont
) {
pushed = 1;
lastClientX = e.clientX;
lastClientY = e.clientY;
e.preventDefault();
}
}, 0
);
_window[addEventListener](
mouseup, cont.mu = function() {pushed = 0;}, 0
);
_window[addEventListener](
mousemove,
cont.mm = function(e) {
if (pushed) {
(scroller = el.scroller||el).scrollLeft -=
newScrollX = (- lastClientX + (lastClientX=e.clientX));
scroller.scrollTop -=
newScrollY = (- lastClientY + (lastClientY=e.clientY));
if (el == _document.body) {
(scroller = _document.documentElement).scrollLeft -= newScrollX;
scroller.scrollTop -= newScrollY;
}
}
}, 0
);
})(dragged[i++]);
}
}
if (_document.readyState == 'complete') {
reset();
} else {
_window[addEventListener]('load', reset, 0);
}
exports.reset = reset;
}));