Bootstrap 4 灵活的响应式导航栏菜单

Posted

技术标签:

【中文标题】Bootstrap 4 灵活的响应式导航栏菜单【英文标题】:Bootstrap 4 flexible responsive navbar menu 【发布时间】:2019-03-07 12:04:06 【问题描述】:

请注意,我不是在问如何对齐导航菜单中的项目(左或右),而是如何将项目从导航栏动态移动到下拉菜单。

我在我的项目中使用 Bootstrap 4.1。我的顶部主菜单包含许多链接。最后一项是包含附加链接的下拉列表:

我希望在调整窗口大小时,将标题中没有足够空间的正确项目移动到下拉项目中。

我想要的:

但是在调整大小时,项目正在缩小。然后,对于“md”(和更小的)断点,默认导航栏功能被激活:

使用 flexbox 的解决方案也是可以接受的。 使用默认 Bootstrap 导航栏链接到简单演示:CodePen

<nav class="navbar navbar-expand-lg navbar-light bg-light">
  <a class="navbar-brand" href="#">Navbar</a>
  <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
    <span class="navbar-toggler-icon"></span>
  </button>
  <div class="collapse navbar-collapse" id="navbarNavDropdown">
    <ul class="navbar-nav">
      <li class="nav-item active">
        <a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>
      </li>
      <li class="nav-item">
        <a class="nav-link" href="#">Features</a>
      </li>
      <li class="nav-item">
        <a class="nav-link" href="#">Pricing</a>
      </li>
      <li class="nav-item">
        <a class="nav-link" href="#">Menu item 4</a>
      </li>
      <li class="nav-item">
        <a class="nav-link" href="#">Menu item 5</a>
      </li>
      <li class="nav-item">
        <a class="nav-link" href="#">Menu item 6</a>
      </li>
      <li class="nav-item">
        <a class="nav-link" href="#">Menu item 7</a>
      </li>
      <li class="nav-item">
        <a class="nav-link" href="#">Menu item 8</a>
      </li>
      <li class="nav-item dropdown">
        <a class="nav-link dropdown-toggle" href="#" id="navbarDropdownMenuLink" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
          Dropdown Menu
        </a>
        <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
          <a class="dropdown-item" href="#">Menu item 9</a>
          <a class="dropdown-item" href="#">Menu item 10</a>
          <a class="dropdown-item" href="#">About</a>
          <a class="dropdown-item" href="#">Help</a>
          <a class="dropdown-item" href="#">Sign out</a> 
        </div>
      </li>
    </ul>
  </div>
</nav>

谢谢!

编辑:

这是我目前正在使用的窗口的调整大小功能:

let addMenu = $("#navbarNavDropdown > ul >li.dropdown"),
    addMenuList = addMenu.children("ul"),
    menuItems = $("#navbarNavDropdown > ul > li:visible:not('.dropdown')");

function _resize() 
    var itemsWidth = 0,
        startWrap = false,
        navWidth = $("#navbarNavDropdown").width() - addMenu.width();
    menuItems.each(function () 
        if (startWrap == false) 
            if (itemsWidth + $(this).width() < navWidth) 
                itemsWidth += $(this).width();
            
            else 
                startWrap = true;
                addMenuList.prepend(this);
            
        
        else 
            addMenuList.prepend(this);
        
    );

window.onresize = _resize;

上面的链接也更新了。

在缩小屏幕时有效,但我需要实现:

增加屏幕宽度时; 在“md”(或更小)断点中,使用默认引导程序的功能

【问题讨论】:

@Zim,我看到您已将问题标记为“重复”,但我不是在问如何对齐导航菜单中的项目(左或右),而是如何从导航栏到下拉菜单。 帖子已经用简单的代码更新了。 【参考方案1】:

改为使用高度来检测导航栏项目何时被包裹。您可能需要调整 JS 以适应其他菜单项(关于、帮助、退出)。这是 Bootstrap 4 的 jQuery 函数...

var autocollapse = function (menu,maxHeight) 

    var nav = $(menu);
    var navHeight = nav.innerHeight();
    if (navHeight >= maxHeight) 
        $(menu + ' .dropdown').removeClass('d-none');
        while (navHeight > maxHeight) 
            var children = nav.children(menu + ' li:not(:last-child)');
            var count = children.length;
            $(children[count - 1]).prependTo(menu + ' .dropdown-menu');
            navHeight = nav.innerHeight();
        
    
    else 
        var collapsed = $(menu + ' .dropdown-menu').children(menu + ' li');

        if (collapsed.length===0) 
          $(menu + ' .dropdown').addClass('d-none');
        

        while (navHeight < maxHeight && (nav.children(menu + ' li').length > 0) && collapsed.length > 0) 
            collapsed = $(menu + ' .dropdown-menu').children('li');
            $(collapsed[0]).insertBefore(nav.children(menu + ' li:last-child'));
            navHeight = nav.innerHeight();
        

        if (navHeight > maxHeight)  
            autocollapse(menu,maxHeight);
        
    
;


$(document).ready(function () 

    // when the page laods
    autocollapse('#nav',50); 

    // when the window is resized
    $(window).on('resize', function () 
        autocollapse('#nav',50); 
    );

);

演示:https://www.codeply.com/go/wKWHgsMXah


相关:Bootstrap navbar hide menu elements when resizing

【讨论】:

谢谢你,@Zim!是的,它工作正常!我之前没有写,因为我想添加我的自定义更改,然后上传更新的演示。我已经使用了您的代码 + 一些额外的更改: - 在下拉菜单中添加“固定”项目,无论屏幕分辨率如何; - 在移动设备上,从下拉列表中移出所有项目(以使用默认 Bootstrap 的移动导航栏); - 调整大小时添加下拉分隔符; Demo here【参考方案2】:

@Zim 的上述回复按我的预期工作。谢谢你,@Zim! 我根据项目的需要做了一些更改,例如:

在下拉菜单中添加“固定”项目,无论屏幕分辨率如何。它们将始终在下拉列表中; 在移动设备上,从下拉列表中移出所有项目,以使用默认 Bootstrap 的移动导航栏; 添加下拉分隔符,以显示在“固定”项目上方。

Demo here

$(function() 
var autocollapse = function (menu, maxHeight) 
    var nav = $(menu);

    if ($(window).width() <= 768) 
        $(menu + ' .additional-dropdown-menu').children(menu + ' li').each(function() 
            _moveDropdownItemToNavbar(this, nav, menu);
        );
        $(menu + ' .additional-menu').hide();
    
    else 
        $(menu + ' .additional-menu').show();
        var navHeight = nav.innerHeight();
        if (navHeight >= maxHeight) 
            while (navHeight > maxHeight) 
                var children = nav.children(menu + ' li:not(:last-child)');
                var count = children.length;
                $(children[count - 1]).prependTo(menu + ' .additional-dropdown-menu').removeClass("nav-item").find("a").toggleClass("nav-link dropdown-item");
                navHeight = nav.innerHeight();
                $(menu + ' .additional-dropdown-menu .extra-divider').removeClass("d-md-none"); //show the extra divider when items is added to the additional dropdown
            
        
        else 
            var collapsed = $(menu + ' .additional-dropdown-menu').children(menu + ' li');

            if (collapsed.not(".additional-item-locked").length == 0)  //if there are only locked items - hide the extra divider. 
                $(menu + ' .additional-dropdown-menu .extra-divider').addClass("d-md-none");
            
            while (navHeight < maxHeight && (nav.children(menu + ' li').length > 0) && collapsed.length > 0) 
                collapsed = $(menu + ' .additional-dropdown-menu').children('li:not(.additional-item-locked)');
                _moveDropdownItemToNavbar(collapsed[0], nav, menu);
                navHeight = nav.innerHeight();
            

            if (navHeight > maxHeight) 
                autocollapse(menu, maxHeight);
            
        
    
;

function _moveDropdownItemToNavbar(item, nav, menu) 
    $(item).insertBefore(nav.children(menu + ' li:last-child')).addClass("nav-item").find("a").toggleClass("nav-link dropdown-item");


autocollapse('#navbar > ul', 50);

// when the window is resized
$(window).on('resize', function () 
    autocollapse('#navbar > ul', 50);
);

);

【讨论】:

以上是关于Bootstrap 4 灵活的响应式导航栏菜单的主要内容,如果未能解决你的问题,请参考以下文章

Bootstrap 导航栏响应式下拉菜单不响应触摸

Bootstrap 4 使用切换按钮连接侧面菜单(响应式)

Angular UI Bootstrap 响应式导航栏下拉菜单在新版本中无法正常工作

在 Bootstrap 中禁用响应式(移动)导航栏

带有 jQ​​uery 和 Bootstrap 3 的可折叠响应式侧边栏菜单

Bootstrap 4 导航栏切换损坏