Горизонтальное stretch меню

Есть горизонтальное меню и кнопка more.

Если пункты меню не вмещаются во всю доступную ширину, то остальные пункты должны "прятаться" в dropdown меню. При клике на кнопку, раскрывается меню с "оставшимися пунктами.

Все это должно работать и при ресайзе и при загрузке.

Код:

function adaptMenu() {
  var $category = $('.category'),
    $categoryList = $category.find('.category-list'),
    $categoryMore = $category.find('.category-more'),
    $categoryMoreDD = $categoryMore.closest('.dropdown'),
    $categoryMoreMenu = $categoryMoreDD.find('.dropdown-menu'),
    $categoryItems = $categoryList.find('.category-item');

  var $visible = [],
    $hidden = [];

  $categoryItems.hide();
  var $width = $categoryList.width();
  $categoryItems.show();
  var $total = 0;

  $categoryItems.each(function() {
    var item = $(this);

    item.css({
      'width': 'auto'
    });
    $total += item.width();

    if ($total < $width) {
      $visible.push(item);
    } else {
      $hidden.push(item);
    }

  });

  if ($hidden.length > 0) {
    $categoryMoreMenu.append($hidden);
  } else {
    $categoryMoreMenu.find('li').hide();
  }


}


$(window).on('load', function() {
  adaptMenu();
});

$(window).on('resize', function() {
  adaptMenu();
});

adaptMenu();
.category-list {
  overflow: hidden;
}

.dropdown .category-item {
  width: 100%;
  margin: 0 !important;
}

.dropdown .cat {
  width: 100%;
}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js" integrity="sha512-bLT0Qm9VnAYZDflyKcBaQ2gg0hSYNQrJ8RilYldYQ1FxQYoCLtUjuuRuZo+fjqhx/qtq/1itJ0C2ejDxltZVFg==" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-ho+j7jyWK8fNQe+A12Hb8AhRq26LrZ/JpcUGGOn+Y7RsweNrtN/tE3MoK7ZeZDyx" crossorigin="anonymous"></script>


<div class="category">
  <div class="container-fluid">
    <div class="row">
      <div class="col-9">
        <ul class="category-list list-unstyled d-flex w-100">
          <li class="category-item px-2"><a href="" class="cat btn btn-primary">1</a></li>
          <li class="category-item px-2"><a href="" class="cat btn btn-primary">2</a></li>
          <li class="category-item px-2"><a href="" class="cat btn btn-primary">3</a></li>
          <li class="category-item px-2"><a href="" class="cat btn btn-primary">4</a></li>
          <li class="category-item px-2"><a href="" class="cat btn btn-primary">5</a></li>
          <li class="category-item px-2"><a href="" class="cat btn btn-primary">6</a></li>
          <li class="category-item px-2"><a href="" class="cat btn btn-primary">7</a></li>
          <li class="category-item px-2"><a href="" class="cat btn btn-primary">8</a></li>
          <li class="category-item px-2"><a href="" class="cat btn btn-primary">9</a></li>
          <li class="category-item px-2"><a href="" class="cat btn btn-primary">10</a></li>
          <li class="category-item px-2"><a href="" class="cat btn btn-primary">11</a></li>
          <li class="category-item px-2"><a href="" class="cat btn btn-primary">12</a></li>
          <li class="category-item px-2"><a href="" class="cat btn btn-primary">13</a></li>
          <li class="category-item px-2"><a href="" class="cat btn btn-primary">14</a></li>
          <li class="category-item px-2"><a href="" class="cat btn btn-primary">15</a></li>
          <li class="category-item px-2"><a href="" class="cat btn btn-primary">16</a></li>
          <li class="category-item px-2"><a href="" class="cat btn btn-primary">17</a></li>
          <li class="category-item px-2"><a href="" class="cat btn btn-primary">18</a></li>
          <li class="category-item px-2"><a href="" class="cat btn btn-primary">19</a></li>
          <li class="category-item px-2"><a href="" class="cat btn btn-primary">20</a></li>
        </ul>
      </div>

      <div class="col-3">
        <div class="dropdown">
          <button class="category-more w-100 btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                More
              </button>
          <div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

Вопрос: как реализовать отображение\скрытие пунктов меню в dropdown меню, которые не вмещаются в доступную видимую ширину меню и при загрузке и при ресайзе?


Ответы (1 шт):

Автор решения: Sevastopol'

Есть у меня одно интересное решение. Автора правда не знаю, но ему спасибо, отлично получилось, и ничего больше делать не нужно. Поделюсь с вами:

var $nav = $('.nav');
var $btn = $('.nav button');
var $vlinks = $('.nav .visible-links');
var $hlinks = $('.nav .hidden-links');
var breaks = [];

function updateNav() {
  var availableSpace = $btn.hasClass('hidden') ? $nav.width() : $nav.width() - $btn.width() - 30;
  if ($vlinks.width() > availableSpace) {
    breaks.push($vlinks.width());
    $vlinks.children().last().prependTo($hlinks);
    if ($btn.hasClass('hidden')) {
      $btn.removeClass('hidden');
    }
  } else {
    if (availableSpace > breaks[breaks.length - 1]) {
      $hlinks.children().first().appendTo($vlinks);
      breaks.pop();
    }
    if (breaks.length < 1) {
      $btn.addClass('hidden');
      $hlinks.addClass('hidden');
    }
  }
  $btn.attr("count", breaks.length);
  if ($vlinks.width() > availableSpace) {
    updateNav();
  }
}
$(window).resize(function() {
  updateNav();
});
$btn.on('click', function() {
  $hlinks.toggleClass('hidden');
});
updateNav();
* {
  margin: 0;
  padding: 0;
}

body {
  margin: 50px 25px;
}

.nav {
  position: relative;
  min-width: 250px;
  background: gold;
  border-top: 1px solid red;
  border-bottom: 1px solid red;
}

.nav a {
  display: block;
  padding: 10px 20px;
  background: gold;
  font-size: 18px;
  color: black;
  text-decoration: none;
}

.nav a:hover {
  color: red;
}

.nav button {
  position: absolute;
  height: 100%;
  right: 0;
  padding: 0 15px;
  border: 0;
  outline: none;
  background-color: red;
  color: #fff;
  cursor: pointer;
}

.nav button:hover {
  background-color: indianred;
}

.nav button::after {
  content: attr(count);
  position: absolute;
  width: 25px;
  height: 25px;
  left: -16px;
  top: 7px;
  text-align: center;
  background-color: red;
  color: #fff;
  font-size: 14px;
  line-height: 25px;
  border-radius: 50%;
  border: 2px solid #fff;
  font-weight: bold;
}

.nav button:hover::after {
  transform: scale(1.05);
}

.nav .hamburger {
  position: relative;
  width: 32px;
  height: 4px;
  background: #fff;
  margin: auto;
}

.nav .hamburger:before,
.nav .hamburger:after {
  content: '';
  position: absolute;
  left: 0;
  width: 32px;
  height: 4px;
  background: #fff;
}

.nav .hamburger:before {
  top: -8px;
}

.nav .hamburger:after {
  bottom: -8px;
}

.nav .visible-links {
  display: inline-table;
}

.nav .visible-links li {
  display: table-cell;
  border-left: 1px solid red;
}

.nav .hidden-links {
  position: absolute;
  right: 0px;
  top: 100%;
  border-left: 1px solid red;
  border-right: 1px solid red;
  border-bottom: 1px solid red;
}

.nav .hidden-links li {
  display: block;
  border-top: 1px solid red;
}

.nav .visible-links li:first-child {
  font-weight: bold;
}

.nav .visible-links li:first-child a {
  color: red !important;
}

.nav .hidden {
  visibility: hidden;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<nav class='nav'>
  <button><div class="hamburger"></div></button>
  <ul class='visible-links'>
    <li><a href='#'>Главная</a></li>
    <li><a href='#'>Проекты</a></li>
    <li><a href='#'>Заказы</a></li>
    <li><a href='#'>Выполненные работы</a></li>
    <li><a href='#'>Отзывы</a></li>
    <li><a href='#'>Наши планы</a></li>
    <li><a href='#'>Инвесторы</a></li>
    <li><a href='#'>Контакты</a></li>
  </ul>
  <ul class='hidden-links hidden'></ul>
</nav>

→ Ссылка