最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Alter Bootstrap nav tabs row wrapping - Stack Overflow

programmeradmin0浏览0评论

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
Add a comment  | 

6 Answers 6

Reset to default 6 +100

I 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...

发布评论

评论列表(0)

  1. 暂无评论