在响应式导航中添加更多列表按钮

我有一个让我们说12个项目的导航,当分辨率变小时,项目会在新行中下降。 当项目不再适合导航时,我需要在导航的右侧放置一个“更多”下拉按钮。 并把那个不适合下拉的项目。 如果你不理解我,下面有图片。

但问题是导航项的宽度并不总是相同,因为导航项是从REST api生成的。

我试着制作jQuery脚本来计算项目宽度并将它们添加到导航中。 这是我创建的脚本,我匆忙制作,所以它非常糟糕。

我需要帮助如何正确计算项目和导航宽度,并计算何时添加项目到导航或从导航中删除项目。

如果你没有得到它,这是图像: http : //img.hr/aagV

/* * Here we check how many items can we put on the navigation bar * If item doesn't fit we clone it on the more dropdown button */ function removeMany() { var i = $items.length - 1; if (itemsWidth > navWidth) { while (itemsWidth > navWidth) { $($items[i]).removeClass('first-level-item').addClass('second-level-item'); dropdownItems.push($items[i]); $($items[i]).removeClass('showed'); $items.pop(); i--; getItemsWidth(); } $nav.append($navMore); dropdownItems.reverse().forEach(function (element, index, array) { $('ul.second-level').append(element); }); getItems(); } } //If window is resized to bigger resolution we need to put back items on the navbar function addMany() { var i = dropdownItems.length - 1; if (dropdownItems.length != 0) { do { $('ul.first-level').append(dropdownItems.reverse()[i]); $items.push(dropdownItems[i]); dropdownItems.pop(); i--; getItemsWidth(); } while (itemsWidth < navWidth); $navMore.remove(); $items.each(function (i) { $(this).addClass('first-level-item showed').removeClass('second-level-item'); }); if (!(dropdownItems != 0)) { return; } else { $nav.append($navMore); } } } 
 body { margin: 0; padding: 0; border: 0; } ul, li { margin: 0; padding: 0; list-style: none; } ul.second-level li { display: block !important; } ul.second-level li > a { color: black; } a { color: #fff; text-decoration: none; text-transform: uppercase; } .second-level-item a { color: #333 !important; } .navigation { width: 960px; max-width: 100%; background: #211; color: #aaa; margin: 0 auto; } .first-level .first-level-item { display: inline-block; padding: 10px; } .first-level .item-more { display: inline-block; } .first-level .item-more .second-level-item { display: inline-block; } .second-level { position: absolute; top: 100%; right: 0; width: 200px; background: #fff; padding: 10px; box-shadow: 0 4px 10px rgba(0, 0, 0, 0.4); } .has-second-level { position: relative; } .has-second-level .second-level { display: none; } .has-second-level:hover { background: #fff; color: #000; } .has-second-level:hover .second-level { display: block; } /*# sourceMappingURL=style.css.map */ 
      DropDown         

这个问题太旧了,但我想发布我的答案。 也许这是更清洁,更简单的方式。 我创建了一支笔: https : //codepen.io/sergi95/pen/bmNoML

  

 const $mainMenu = $("#mainMenu"); const $autoNav = $("#autoNav"); const $autoNavMore = $("#autoNavMore"); const $autoNavMoreList = $("#autoNavMoreList"); autoNavMore = () => { let childNumber = 2; if($(window).width() >= 320) { // GET MENU AND NAV WIDTH const $menuWidth = $mainMenu.width(); const $autoNavWidth = $autoNav.width(); if($autoNavWidth > $menuWidth) { // CODE FIRES WHEN WINDOW SIZE GOES DOWN $autoNav.children(`li:nth-last-child(${childNumber})`).prependTo($autoNavMoreList); autoNavMore(); } else { // CODE FIRES WHEN WINDOW SIZE GOES UP const $autoNavMoreFirst = $autoNavMoreList.children('li:first-child').width(); // CHECK IF ITEM HAS ENOUGH SPACE TO PLACE IN MENU if(($autoNavWidth + $autoNavMoreFirst) < $menuWidth) { $autoNavMoreList.children('li:first-child').insertBefore($autoNavMore); } } if($autoNavMoreList.children().length > 0) { $autoNavMore.show(); childNumber = 2; } else { $autoNavMore.hide(); childNumber = 1; } } } // INIT autoNavMore(); $(window).resize(autoNavMore); .main-menu { max-width: 800px; } .main-nav { display: inline-flex; padding: 0; list-style: none; } .main-nav li a { padding: 10px; text-transform: capitalize; white-space: nowrap; font-size: 30px; font-family: sans-serif; text-decoration: none; } .more-btn { color: red; } .auto-nav-more { position: relative; } .auto-nav-more-list { position: absolute; right: 0; opacity: 0; visibility: hidden; transition: 0.2s; text-align: right; padding: 0; list-style: none; background: grey; border-radius: 4px; } .auto-nav-more:hover .auto-nav-more-list { opacity: 1; visibility: visible; } 

如果您有固定宽度的列表项,那么收集额外的列表项并将它们推送到单独的列表中很简单。 这是一个简单的例子。 解释在代码注释中。

全屏查看片段并尝试更改窗口宽度

也是一个小提琴 : http : //jsfiddle.net/abhitalks/860LzgLL/

全屏 : http : //jsfiddle.net/abhitalks/860LzgLL/embedded/result/

片段

 var elemWidth, fitCount, fixedWidth = 120, $menu = $("ul#menu"), $collectedSet; // Assuming that the list-items are of fixed-width. collect(); $(window).resize(collect); function collect() { // Get the container width elemWidth = $menu.width(); // Calculate how many list-items can be accomodated in that width fitCount = Math.floor(elemWidth / fixedWidth) - 1; // Create a new set of list-items more than the fit count $collectedSet = $menu.children(":gt(" + fitCount + ")"); // Empty the collection submenu and add the cloned collection set $("#submenu").empty().append($collectedSet.clone()); } 
 * { box-sizing: border-box; margin: 0; padding: 0; } div { position: relative; background-color: #ccc; height: 32px; overflow: visible; } ul#menu, ol { height: 32px; max-width: 80%; overflow: hidden; } ul#menu > li, ol > li { display: block; float: left; height: 32px; width: 120px; padding: 4px 8px; } ol { position: absolute; right: 0; top: 0; overflow: visible; } ol > li { min-width: 120px; } ol ul { position: absolute; top: 120%; right: 10%; } ol li ul > li { list-style: none; background-color: #eee; border: 1px solid gray; padding: 4px 8px;} 
  
  1. Collected

可以并且应该进行优化(因为我测试的效率非常低),但这取决于您。

 $(document).ready(function(){ var moreW = $(".more").outerWidth(), //width of your "more" element totalW = -moreW, //cumulated width of list elements totalN = $('.nav li').length - 1, //number of elements minus the "more" element dw = document.documentElement.clientWidth; $('.nav li').each(function(){ totalW += $(this).outerWidth(); }); function moveToDropdown(){ dw = document.documentElement.clientWidth; //moves elements into the list while(totalW > (dw - moreW)){ var temp = $(".nav li:nth-last-child(2)"); //element to be moved totalW = totalW - temp.outerWidth(); $(".dropdown").append(temp.clone()); temp.remove(); } //moves elements out of the list var newList = $('.dropdown li').length; //check if we have elements if(newList > 0){ var element = $('.dropdown li:last-child'), //element to be moved elementW = $('.dropdown li:last-child').outerWidth(); //width of element to be moved if(totalW + elementW < dw - moreW){ while(totalW + elementW < dw - moreW ){ var element = $('.dropdown li:last-child'), elementW = $('.dropdown li:last-child').outerWidth(); totalW = totalW + elementW; $(".nav > li:last-child").before(element.clone()); element.remove(); } } } } moveToDropdown(); $(window).resize(moveToDropdown) }); 
 .clearfix:after{ display:block; content:''; clear:both; } body,html{ width:100%; height:100%; margin:0; padding:0; } ul{ list-style:none; width:100%; padding:0; margin:0; } ul li{ float:left; padding:5px; } .nav > li { position:relative; } .nav ul{ position:absolute; top:25px; } 
   

Abhitalks制作的脚本不适用于不同的元素大小。 我修改了一下它的代码:

 $(function() { function makeMenuFit() { //Get data var menuSize = menu.width(); //Determine how many items that fit var menuTotalWidth = 0; var itemThatFit = 0; for(var i = 0; i < menuItems.length; i++) { menuTotalWidth += menuItems[i]; if(menuTotalWidth <= menuSize) { itemThatFit++; continue; } break; } menu.children().css({"display": "block", "width": "auto"}); var collectedSet = menu.children(":gt(" + (itemThatFit - 1) + ")"); $("#submenu").empty().append(collectedSet.clone()); collectedSet.css({"display": "none", "width": "0"}); } var menu = $(".tabletNavigation > ul"); var menuItems = []; menu.children().each(function() { menuItems.push($(this).outerWidth()); }); $(window).resize(makeMenuFit); makeMenuFit(); });