With Bootstrap 3, rows of nav-tabs wrap in a way where the widest rows tend to be at the top while the shorter rows are at the bottom:
This leaves the tabs looking awkward and unbalanced. Is there a way that nav-tabs can be modified so that the rows are wider at the bottom? More like this:
Here's the JSFiddle that produced the first image.
<link rel="stylesheet" href=".3.5/css/bootstrap.min.css">
<div class="container">
<div class="row">
<div class="col-sm-6">
<ul class="nav nav-tabs">
<li class="active"><a href="#">Foo Bar 1</a></li>
<li><a href="#">FooBar 2</a></li>
<li><a href="#">FooBar 3</a></li>
<li><a href="#">FooBar 4</a></li>
<li><a href="#">FooBar 5</a></li>
<li><a href="#">FooBar 6</a></li>
<li><a href="#">FooBar 7</a></li>
<li><a href="#">FooBar 8</a></li>
<li><a href="#">FooBar 9</a></li>
<li><a href="#">FooBar 10</a></li>
<li><a href="#">FooBar 11</a></li>
<li><a href="#">FooBar 12</a></li>
<li><a href="#">FooBarBaz 13</a></li>
<li><a href="#">FooBarBaz 14</a></li>
</ul>
</div>
</div>
</div>
With Bootstrap 3, rows of nav-tabs wrap in a way where the widest rows tend to be at the top while the shorter rows are at the bottom:
This leaves the tabs looking awkward and unbalanced. Is there a way that nav-tabs can be modified so that the rows are wider at the bottom? More like this:
Here's the JSFiddle that produced the first image.
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<div class="container">
<div class="row">
<div class="col-sm-6">
<ul class="nav nav-tabs">
<li class="active"><a href="#">Foo Bar 1</a></li>
<li><a href="#">FooBar 2</a></li>
<li><a href="#">FooBar 3</a></li>
<li><a href="#">FooBar 4</a></li>
<li><a href="#">FooBar 5</a></li>
<li><a href="#">FooBar 6</a></li>
<li><a href="#">FooBar 7</a></li>
<li><a href="#">FooBar 8</a></li>
<li><a href="#">FooBar 9</a></li>
<li><a href="#">FooBar 10</a></li>
<li><a href="#">FooBar 11</a></li>
<li><a href="#">FooBar 12</a></li>
<li><a href="#">FooBarBaz 13</a></li>
<li><a href="#">FooBarBaz 14</a></li>
</ul>
</div>
</div>
</div>
Share
Improve this question
edited Mar 22, 2016 at 6:19
Jonathan
asked Mar 17, 2016 at 3:35
JonathanJonathan
5,10741 silver badges49 bronze badges
3
- Any chance of an image that shows exactly what you want? – Tigger Commented Mar 20, 2016 at 4:48
- @Tigger I just posted an image showing what I'm after - wider rows at the bottom. – Jonathan Commented Mar 21, 2016 at 16:36
- Think that using tabs in this case is terrible. Why not a simple buttons? – Andrew Orlov Commented Mar 25, 2016 at 23:11
6 Answers
Reset to default 6 +100I know it's not the best solution from the performance point of view but, anyway...Hope, this will be helpful. This solution doesn't depends on specific tab width and provides the result you want.
JSFiddle: https://jsfiddle.net/cpxd8eh0/6/
$(function(){
var $container = $('#sync-tabs');
updateTabs($container);
$(window).resize(function(){
updateTabs($container);
});
function updateTabs($tabsContainer){
var $containerWidth = $tabsContainer.width();
var tabWidths = [];
var $tabs = $tabsContainer.find('li');
$tabs.each(function(index, tab){
tabWidths.push($(tab).width());
});
var formattedTabs = [];
var maxWidth = $containerWidth;
var maxWidthSet = false;
var rowWidth = 0;
for(var i = tabWidths.length - 1; i >= 0; i--){
var tabWidth = tabWidths[i];
if(rowWidth + tabWidth > maxWidth){
if(!maxWidthSet){
maxWidth = rowWidth;
maxWidthSet = true;
}
rowWidth = tabWidth;
formattedTabs.unshift($('<div class="spacer"></div>'));
}else{
rowWidth += tabWidth;
}
formattedTabs.unshift($tabs.get(i));
}
var $tempContainer = $('<div></div>');
formattedTabs.forEach(function(tab, index){
$tempContainer.append(tab);
});
$tabsContainer.html($tempContainer.html());
}
});
I have updated the answer with a new and improved solution. Here is a demo. _.debounce
is a function from Lodash which is being used to improve performance of the resize watcher.
function setTabs() {
let availableWidth = $('#nav-bar').outerWidth();
let liNodes = $('#nav-bar li');
liNodes.removeClass('clear');
let filledWidth = 0;
for (var i=liNodes.length-1; i>=0; i--) {
let currentWidth = $(liNodes[i]).outerWidth();
if (filledWidth + currentWidth <= availableWidth)
filledWidth += currentWidth;
else {
$(liNodes[i+1]).addClass('clear');
availableWidth = filledWidth;
filledWidth = currentWidth;
}
}
}
setTabs();
$(window).resize(_.debounce(setTabs, 200));
Are you trying to do something like shown in the fiddle
You can explicitly use css clear trick to achieve what you want.
.clear {
clear: both;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"/>
<div class="container">
<div class="row">
<div class="col-sm-6">
<ul class="nav nav-tabs" id="sync-tabs">
<li class="active"><a href="#">Foo Bar 1</a></li>
<li><a href="#">FooBar 2</a></li>
<li><a href="#">FooBar 3</a></li>
<li><a href="#">FooBar 4</a></li>
<li class="clear"><a href="#">FooBar 5</a></li>
<li><a href="#">FooBar 6</a></li>
<li><a href="#">FooBar 7</a></li>
<li><a href="#">FooBar 8</a></li>
<li><a href="#">FooBar 9</a></li>
<li class="clear"><a href="#">FooBar 10</a></li>
<li><a href="#">FooBar 11</a></li>
<li><a href="#">FooBar 12</a></li>
<li><a href="#">FooBar 13</a></li>
<li><a href="#">FooBar 14</a></li>
</ul>
</div>
</div>
</div>
I didn't understand what exactly you are looking for, and added following css to look good https://jsfiddle.net/2tu6a2yh/2/
.nav-tabs {
display: table;
table-layout: fixed;
width : 100%;
}
.nav-tabs li {
display: table-cell;
width:120px; // constant width
}
I think you need to set the column sizes for each list item for a more consistent look. Otherwise positions are determined according to the text length they contain. I think, if you make a few trial you'll find the combination you want for each screen size. Try something like following approach
<div class="container">
<div class="row">
<div class="col-sm-6">
<ul class="nav nav-tabs" id="sync-tabs">
<li class="active col-sm-4"><a href="#">Foo Bar 1</a></li>
<li class="col-sm-4"><a href="#">FooBar 2</a></li>
<li class="col-sm-4"><a href="#">FooBar 3</a></li>
<li class="col-sm-4"><a href="#">FooBar 4</a></li>
<li class="col-sm-4"><a href="#">FooBar 5</a></li>
<li class="col-sm-4"><a href="#">FooBar 6</a></li>
<li class="col-sm-3"><a href="#">FooBar 7</a></li>
<li class="col-sm-3"><a href="#">FooBar 8</a></li>
<li class="col-sm-3"><a href="#">FooBar 9</a></li>
<li class="col-sm-3"><a href="#">FooBar 10</a></li>
<li class="col-sm-3"><a href="#">FooBar 11</a></li>
<li class="col-sm-3"><a href="#">FooBar 12</a></li>
<li class="col-sm-3"><a href="#">FooBarBaz 13</a></li>
<li class="col-sm-3"><a href="#">FooBarBaz 14</a></li>
</ul>
</div>
Here is a fiddle that i have done according to your requirements
FIDDLE LINK
.nav-tabs
{
display: -webkit-flex;
display: flex;
-webkit-flex-direction: column;
flex-direction: column;
-webkit-align-items: flex-start;
align-items: flex-start;
}
<div class="container">
<div class="row">
<div class="col-sm-6">
<ul class="nav nav-tabs" id="sync-tabs">
<li class="active"><a href="#">Foo Bar 1</a></li>
<li><a href="#">FooBar 2</a></li>
<li><a href="#">FooBar 3</a></li>
<li><a href="#">FooBar 4</a></li>
<li><a href="#">FooBar 5</a></li>
<li><a href="#">FooBar 6</a></li>
<li><a href="#">FooBar 7</a></li>
<li><a href="#">FooBar 8</a></li>
<li><a href="#">FooBar 9</a></li>
<li><a href="#">FooBar 10</a></li>
<li><a href="#">FooBar 11</a></li>
<li><a href="#">FooBar 12</a></li>
<li><a href="#">FooBarBaz 13</a></li>
<li><a href="#">FooBarBaz 14</a></li>
</ul>
</div>
</div>
</div>
UPDATED FIDDLE LINK AS PER THE IMAGE GIVEN
Hope this helps...