题 如何在悬停而不是单击时使Twitter Bootstrap菜单下拉列表


我想让我的Bootstrap菜单在悬停时自动下拉,而不必单击菜单标题。我还想丢失菜单标题旁边的小箭头。


1039
2018-01-16 09:36


起源


有一个解决方案,所以mikko的答案是正确的,但现在有一个插件专门针对这种情况。 自举悬停下拉 - HenryW
查看我新发布的正确插件,它可以防止以下CSS和js解决方案的问题,并且可以在iOS和带有触摸事件的现代桌面浏览器上正常工作。即使是aria属性也可以正常工作: github.com/istvan-ujjmeszaros/bootstrap-dropdown-hover - István Ujj-Mészáros
我用一个bootstrap导航栏制作了一个纯CSS3下拉列表,在CodePen上查看它 纯CSS3下拉列表 - Gothburz
如果你真的需要它,请三思而后行? Bootstrap用于自适应站点。这意味着它们也将用于带触摸控制的设备上。这就是它以这种方式设计的原因。触摸屏上没有“悬停”。 - Serj.by
可能重复 带悬停的Bootstrap下拉列表 - slugster


答案:


我基于最新的(v2.0.2)Bootstrap框架创建了一个纯粹的悬停下拉菜单,该框架支持多个子菜单,并且我认为我会为将来的用户发布它:

body {
  padding-top: 60px;
  padding-bottom: 40px;
}

.sidebar-nav {
  padding: 9px 0;
}

.dropdown-menu .sub-menu {
  left: 100%;
  position: absolute;
  top: 0;
  visibility: hidden;
  margin-top: -1px;
}

.dropdown-menu li:hover .sub-menu {
  visibility: visible;
}

.dropdown:hover .dropdown-menu {
  display: block;
}

.nav-tabs .dropdown-menu,
.nav-pills .dropdown-menu,
.navbar .dropdown-menu {
  margin-top: 0;
}

.navbar .sub-menu:before {
  border-bottom: 7px solid transparent;
  border-left: none;
  border-right: 7px solid rgba(0, 0, 0, 0.2);
  border-top: 7px solid transparent;
  left: -7px;
  top: 10px;
}

.navbar .sub-menu:after {
  border-top: 6px solid transparent;
  border-left: none;
  border-right: 6px solid #fff;
  border-bottom: 6px solid transparent;
  left: 10px;
  top: 11px;
  left: -6px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.2/css/bootstrap.min.css" rel="stylesheet" />

<div class="navbar navbar-fixed-top">
  <div class="navbar-inner">
    <div class="container-fluid">
      <a data-target=".nav-collapse" data-toggle="collapse" class="btn btn-navbar">
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
      </a>
      <a href="#" class="brand">Project name</a>
      <div class="nav-collapse">
        <ul class="nav">
          <li class="active"><a href="#">Home</a></li>
          <li><a href="#">Link</a></li>
          <li><a href="#">Link</a></li>
          <li><a href="#">Link</a></li>
          <li class="dropdown">
            <a data-toggle="dropdown" class="dropdown-toggle" href="#">Dropdown <b class="caret"></b></a>
            <ul class="dropdown-menu">
              <li>
                <a href="#">2-level Dropdown <i class="icon-arrow-right"></i></a>
                <ul class="dropdown-menu sub-menu">
                  <li><a href="#">Action</a></li>
                  <li><a href="#">Another action</a></li>
                  <li><a href="#">Something else here</a></li>
                  <li class="divider"></li>
                  <li class="nav-header">Nav header</li>
                  <li><a href="#">Separated link</a></li>
                  <li><a href="#">One more separated link</a></li>
                </ul>
              </li>
              <li><a href="#">Another action</a></li>
              <li><a href="#">Something else here</a></li>
              <li class="divider"></li>
              <li class="nav-header">Nav header</li>
              <li><a href="#">Separated link</a></li>
              <li><a href="#">One more separated link</a></li>
            </ul>
          </li>
        </ul>
        <form action="" class="navbar-search pull-left">
          <input type="text" placeholder="Search" class="search-query span2">
        </form>
        <ul class="nav pull-right">
          <li><a href="#">Link</a></li>
          <li class="divider-vertical"></li>
          <li class="dropdown">
            <a class="#" href="#">Menu</a>
          </li>
        </ul>
      </div>
      <!-- /.nav-collapse -->
    </div>
  </div>
</div>

<hr>

<ul class="nav nav-pills">
  <li class="active"><a href="#">Regular link</a></li>
  <li class="dropdown">
    <a href="#" data-toggle="dropdown" class="dropdown-toggle">Dropdown <b class="caret"></b></a>
    <ul class="dropdown-menu" id="menu1">
      <li>
        <a href="#">2-level Menu <i class="icon-arrow-right"></i></a>
        <ul class="dropdown-menu sub-menu">
          <li><a href="#">Action</a></li>
          <li><a href="#">Another action</a></li>
          <li><a href="#">Something else here</a></li>
          <li class="divider"></li>
          <li class="nav-header">Nav header</li>
          <li><a href="#">Separated link</a></li>
          <li><a href="#">One more separated link</a></li>
        </ul>
      </li>
      <li><a href="#">Another action</a></li>
      <li><a href="#">Something else here</a></li>
      <li class="divider"></li>
      <li><a href="#">Separated link</a></li>
    </ul>
  </li>
  <li class="dropdown">
    <a href="#">Menu</a>
  </li>
  <li class="dropdown">
    <a href="#">Menu</a>
  </li>
</ul>

演示


529
2018-04-13 14:46



这是bootstrap中的设计决定,不要打开悬停事件的下拉菜单... - caarlos0
太好了!我也删除了 class="dropdown-toggle" data-toggle="dropdown" 所以只有徘徊,而不是点击会触发菜单。请注意,当您使用自适应样式时,菜单仍然会进入右上方的小按钮,这仍然是由单击触发的。十分感谢! - ptim
为了避免较小的设备(例如电话)上的自动下拉,并且仅允许它以例如最小宽度为例。 768px @media (min-width: 768px) {.dropdown-menu li:hover .sub-menu {visibility: visible;}} 和 @media (min-width: 768px) {.dropdown:hover .dropdown-menu {display: block;}} - Chris Aelbrecht
另外,为了与可点击的儿童建立链接,您必须删除<a>标签上的“data-toggle ='下拉列表”。 - joan16v
这是一个与最新的Bootstrap 3版本一起使用的代码: jsfiddle.net/sgruenwald/2tt8f8xg - Stefan Gruenwald


要使菜单在悬停时自动停止,那么可以使用基本CSS实现。您需要将选择器设计为隐藏菜单选项,然后将其设置为在适当时显示为块 li 标签悬停在上面。以twitter bootstrap页面为例,选择器如下:

ul.nav li.dropdown:hover > ul.dropdown-menu {
    display: block;    
}

但是,如果您使用的是Bootstrap的响应功能,则在折叠的导航栏上(在较小的屏幕上)不需要此功能。要避免这种情况,请将以上代码包装在媒体查询中:

@media (min-width: 979px) {
  ul.nav li.dropdown:hover > ul.dropdown-menu {
    display: block;
  }
}

要隐藏箭头(插入符号),这取决于您使用的是Twitter Bootstrap版本2及更低版本还是版本3:

Bootstrap 3

要删除版本3中的插入符号,只需删除HTML即可 <b class="caret"></b> 来自 .dropdown-toggle 锚元素:

<a class="dropdown-toggle" data-toggle="dropdown" href="#">
    Dropdown
    <b class="caret"></b>    <-- remove this line
</a>

Bootstrap 2及更低版本

要删除版本2中的插入符号,您需要更多地了解CSS,我建议查看如何 :after 伪元素更详细。为了让您开始理解,定位和删除twitter bootstrap示例中的箭头,您将使用以下CSS选择器和代码:

a.menu:after, .dropdown-toggle:after {
    content: none;
}

如果你进一步研究这些工作的方式而不仅仅是使用我给你的答案,它将对你有利。

感谢@CocaAkat指出我们错过了“>”儿童组合器,以防止子菜单显示在父鼠标悬停上


874
2018-01-16 10:26



还得补充一下 margin: 0;,否则1px以上的保证金 .dropdown-menu 导致越野行为。 - Salman Abbas
简单的解决方案,但父链接仍然无法点击。我正在使用带有主题的最新引导程序。 - Krunal
注意: 是的确如此 - 这将适用于twitter bootstrap支持的任何浏览器。 @GeorgeEdison这是基本的CSS - IE8不支持哪些部分?如果您遇到问题,请发布问题,而不是误导性评论。 - My Head Hurts
@MyHeadHurts:经过一些进一步的研究后 - 结果 这确实是一个Bootstrap错误 它只在五天前修好了。 - Nathan Osman
@Krunal能够点击链接,你必须删除 data-toggle="dropdown" 属性。 - Raúl Ferràs


除了“My Head Hurts”(这很棒)的回答:

ul.nav li.dropdown:hover ul.dropdown-menu{
    display: block;    
}

有两个挥之不去的问题:

  1. 单击下拉链接将打开下拉菜单。除非用户点击其他地方,否则它将保持打开状态,或者将其悬停在其上,从而创建一个尴尬的UI。
  2. 下拉链接和下拉菜单之间有1px的余量。如果您在下拉菜单和下拉菜单之间缓慢移动,则会导致下拉菜单变为隐藏状态。

(1)的解决方案是从导航链接中删除“class”和“data-toggle”元素

<a href="#">
     Dropdown
     <b class="caret"></b>
</a>

这也使您能够创建指向父页面的链接 - 这是默认实现无法实现的。您只需将“#”替换为您要发送给用户的任何页面即可。

(2)的解决方案是删除.dropdown菜单选择器上的margin-top

.navbar .dropdown-menu {
 margin-top: 0px;
}

221
2018-02-24 18:00



为了解决故意点击,我刚刚删除了 data-toggle="dropdown" 属性,似乎有效。 - Anthony Briggs
导航丸按钮的解决方案(2): .nav-pills .dropdown-menu { margin-top: 0px; } - Loren
为了解决我在上面提到的问题li.dropdown:hover> ul.dropdown-menu - Archimedes Trajano
从导航链接中删除“class”和“data-toggle”属性使其在移动设备和平板电脑上停止正常工作:( - Mosijava
如果您删除了data-toggle =“dropdown”属性,则无法使用键盘展开下拉菜单。所以它不会符合508标准。如何禁用点击但保留键盘功能? - duyn9uyen


我使用了一些jQuery:

// Add hover effect to menus
jQuery('ul.nav li.dropdown').hover(function() {
  jQuery(this).find('.dropdown-menu').stop(true, true).delay(200).fadeIn();
}, function() {
  jQuery(this).find('.dropdown-menu').stop(true, true).delay(200).fadeOut();
});

119
2018-05-22 17:49



喜欢这个。无论如何,我使用JQuery与Bootstrap的东西,并仍然允许触摸屏设备中的默认“点击”功能。 - Duck in Custard
用过这个。我喜欢它仍然允许点击功能,对于手机,但对于桌面,悬停是完美的。 - Stuart
我使用了这个,但也将它扩展为可用于不在导航中的下拉列表。我将类下拉悬停添加到btn-group div并使用此jQuery finder $('ul.nav li.dropdown,。dropdown-hover')。hover(function(){。谢谢! - Brandon
使用这个,很好,很小。 css版本不允许子菜单保持显示,200ms太快,所以我将其更改为 $('ul.nav li.dropdown').hover(function() { $(this).find('.dropdown-menu').stop(true, true).delay(200).fadeIn(); }, function() { $(this).find('.dropdown-menu').stop(true, true).delay(200).fadeOut().hover(function() { $(this).stop(true, true); }); }); :当子菜单悬停时停止fadeOut - Damien
这似乎不适用于anguraljs中包含的jqLit​​e - nuander


这里有很多非常好的解决方案。但我认为我会继续把我的作为另一种选择。这只是一个简单的jQuery代码片段,如果它支持将鼠标悬停在下拉菜单而不是单击,那么就像引导程序一样。我只用版本3对它进行了测试,所以我不知道它是否适用于版本2.将它保存为编辑器中的一个片段,然后按一下键。

<script>
    $(function() {
        $(".dropdown").hover(
            function(){ $(this).addClass('open') },
            function(){ $(this).removeClass('open') }
        );
    });
</script>

基本上,它只是说当你将鼠标悬停在下拉列表上时,它会向它添加开放类。然后就行了。当您停止使用下拉类或子ul / li徘徊在父li上时,它将删除打开的类。显然,这只是众多解决方案中的一种,您可以添加它以使其仅适用于.dropdown的特定实例。或者向父母或孩子添加转换。


64
2018-01-31 17:28



好方案!我还从链接中删除了data-toggle =“dropdown”属性,以便使顶部链接可点击。 - Sergey
这是一个很好的提示谢尔盖。我总是确保顶部链接无处可用,以便它也适用于平板电脑和手机。 - stereoscience
@Sergey我不建议这样做。您将破坏移动用户的功能。他们无法使用悬停功能打开菜单,需要能够单击它。 - Paul
这非常简短,同时仍然可以与触摸屏向后兼容。应该得到更多的支持。 - Max
这看起来非常好。知道如何使用CSS过渡添加一些动画吗? - Fred Rocha


只需在三行代码中自定义CSS样式即可

.dropdown:hover .dropdown-menu {
   display: block;
}

60
2018-04-05 06:24





如果你有一个元素 dropdown 像这样的类(例如):

<ul class="list-unstyled list-inline">
    <li class="dropdown">
        <a data-toggle="dropdown" href="#"><i class="fa fa-bars"></i> Dropdown 1</a>
        <ul class="dropdown-menu">
            <li><a href="">Item 1</a></li>
            <li><a href="">Item 2</a></li>
            <li><a href="">Item 3</a></li>
            <li><a href="">Item 4</a></li>
            <li><a href="">Item 5</a></li>
        </ul>
    </li>
    <li class="dropdown">
        <a data-toggle="dropdown" href="#"><i class="fa fa-user"></i> Dropdown 2</a>
        <ul class="dropdown-menu">
            <li><a href="">Item A</a></li>
            <li><a href="">Item B</a></li>
            <li><a href="">Item C</a></li>
            <li><a href="">Item D</a></li>
            <li><a href="">Item E</a></li>
        </ul>
    </li>
</ul>

然后你可以让鼠标悬停在下拉菜单上,而不是必须点击它的标题,使用这段jQuery代码:

<script>
    $('.dropdown').hover(
        function() {
            $(this).find('.dropdown-menu').stop(true, true).delay(200).fadeIn();
        },
        function() {
            $(this).find('.dropdown-menu').stop(true, true).delay(200).fadeOut();
        }
    );

    $('.dropdown-menu').hover(
        function() {
            $(this).stop(true, true);
        },
        function() {
            $(this).stop(true, true).delay(200).fadeOut();
        }
    );
</script>

这是一个演示

这个答案依赖于 @Michael回答,我做了一些更改,并添加了一些补充,以使下拉菜单正常工作


20
2017-09-27 21:13





[更新] 该插件已开启 GitHub上 我正在进行一些改进(比如仅使用数据属性(不需要JS)。我将代码留在下面,但它与GitHub上的代码不同。

我喜欢纯粹的CSS版本,但是在它关闭之前有一个延迟是很好的,因为它通常是一个更好的用户体验(即不会因为在下拉列表外1 px的鼠标滑动而受到惩罚等),并且如评论中所述,你需要处理1px的保证金,或者当你从原始按钮移动到下拉列表时,导航器有时意外关闭等。

我创建了一个快速的小插件,我已经在几个网站上使用它并且它工作得很好。每个导航项都是独立处理的,因此它们有自己的延迟计时器等。

JS

// outside the scope of the jQuery plugin to
// keep track of all dropdowns
var $allDropdowns = $();

// if instantlyCloseOthers is true, then it will instantly
// shut other nav items when a new one is hovered over
$.fn.dropdownHover = function(options) {

    // the element we really care about
    // is the dropdown-toggle's parent
    $allDropdowns = $allDropdowns.add(this.parent());

    return this.each(function() {
        var $this = $(this).parent(),
            defaults = {
                delay: 500,
                instantlyCloseOthers: true
            },
            data = {
                delay: $(this).data('delay'),
                instantlyCloseOthers: $(this).data('close-others')
            },
            options = $.extend(true, {}, defaults, options, data),
            timeout;

        $this.hover(function() {
            if(options.instantlyCloseOthers === true)
                $allDropdowns.removeClass('open');

            window.clearTimeout(timeout);
            $(this).addClass('open');
        }, function() {
            timeout = window.setTimeout(function() {
                $this.removeClass('open');
            }, options.delay);
        });
    });
};  

delay 参数是非常自我解释的,而且 instantlyCloseOthers 当你将鼠标悬停在新的下拉列表上时,它会立即关闭所有其他下拉列表。

不是纯粹的CSS,但希望能在这么晚的时候帮助其他人(即这是一个旧线程)。

如果你愿意,你可以看到我经历的不同过程(在讨论中 #concrete5 IRC)通过这个要点中的不同步骤使其工作: https://gist.github.com/3876924

插件模式方法更加清晰,可以支持个人计时器等。

博客文章 更多。


19
2017-10-12 03:02





这对我有用:

.dropdown:hover .dropdown-menu {
    display: block;
}

15
2017-10-06 11:47



然而,随着移动 - 它很奇怪。 - Radmation
没有在手机上查看 - Amay Kulkarni


使用jQuery更好:

jQuery('ul.nav li.dropdown').hover(function() {
  jQuery(this).find('.dropdown-menu').stop(true, true).show();
  jQuery(this).addClass('open');
}, function() {
  jQuery(this).find('.dropdown-menu').stop(true, true).hide();
  jQuery(this).removeClass('open');
});

9
2017-08-17 01:51



我把你的代码更改为 jQuery('ul.nav li.dropdown').hover(function() { jQuery(this).closest('.dropdown-menu').stop(true, true).show(); jQuery(this).addClass('open'); }, function() { jQuery(this).closest('.dropdown-menu').stop(true, true).hide(); jQuery(this).removeClass('open'); }); 所以子菜单不会在悬停时显示。 - farjam
此代码将不再适用于最新版本。 - Paul