css - react - unity dropdown




如何在悬停而不是点击的情况下制作Twitter Bootstrap菜单下拉菜单 (20)

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


jQuery解决方案很好,但它需要处理点击事件(针对移动设备或平板电脑),因为悬停无法正常工作......可能可能会进行一些窗口重新尺寸检测?

Andres Ilich的答案似乎运作良好,但它应该包装在媒体查询中:

@media (min-width: 980px) {

    .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;
    }
}

[更新]插件在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/3876924https://gist.github.com/3876924

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

查看博客文章了解更多信息。


为了让菜单自动停留在悬停状态,可以使用基本的CSS来实现。 您需要将选择器设置为隐藏菜单选项,然后将其设置为当适当的li标签悬停时显示为块。 以twitter引导页面为例,选择器如下所示:

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中删除插入符号,只需从.dropdown-toggle锚点元素中删除HTML <b class="caret"></b>

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

Bootstrap 2和更低

要在版本2中删除插入符号,您需要对CSS有更深入的了解,并且建议查看:after伪元素如何更详细地工作。 为了让你开始理解,在twitter引导示例中定位并移除箭头,可以使用以下CSS选择器和代码:

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

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

感谢@CocaAkat指出我们错过了“>”子组合器,以防止子菜单显示在父项目上


使用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');
});

做到这一点的最好方法是只用触发器触发Bootstrap的点击事件。 这样,它仍然应该保持触摸设备的友好。

$('.dropdown').hover(function(){ 
  $('.dropdown-toggle', this).trigger('click'); 
});

只是想补充一点,如果你有多个下拉菜单(和我一样),你应该写:

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

它会正常工作。


在停止菜单或切换按钮上的悬停之后,我的技巧会在菜单关闭之前添加一些延迟。 您通常会单击以显示导航菜单的<button>#nav_dropdown

$(function() {
  var delay_close_it, nav_menu_timeout, open_it;
  nav_menu_timeout = void 0;
  open_it = function() {
    if (nav_menu_timeout) {
      clearTimeout(nav_menu_timeout);
      nav_menu_timeout = null;
    }
    return $('.navbar .dropdown').addClass('open');
  };
  delay_close_it = function() {
    var close_it;
    close_it = function() {
      return $('.navbar .dropdown').removeClass('open');
    };
    return nav_menu_timeout = setTimeout(close_it, 500);
  };
  $('body').on('mouseover', '#nav_dropdown, #nav_dropdown *', open_it).on('mouseout', '#nav_dropdown', delay_close_it);
  return $('body').on('mouseover', '.navbar .dropdown .dropdown-menu', open_it).on('mouseout', '.navbar .dropdown .dropdown-menu', delay_close_it);
});

在我看来,最好的方法是这样的:

;(function($, window, undefined) {
    // 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 = $this.parent(),
                defaults = {
                    delay: 500,
                    instantlyCloseOthers: true
                },
                data = {
                    delay: $(this).data('delay'),
                    instantlyCloseOthers: $(this).data('close-others')
                },
                settings = $.extend(true, {}, defaults, options, data),
                timeout;

            $parent.hover(function(event) {

                // So a neighbor can't open the dropdown
                if(!$parent.hasClass('open') && !$this.is(event.target)) {
                    return true;
                }

                if(settings.instantlyCloseOthers === true)
                    $allDropdowns.removeClass('open');

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

            // This helps with button groups!
            $this.hover(function() {
                if(settings.instantlyCloseOthers === true)
                    $allDropdowns.removeClass('open');

                window.clearTimeout(timeout);
                $parent.addClass('open');
            });

            // Handle submenus
            $parent.find('.dropdown-submenu').each(function(){
                var $this = $(this);
                var subTimeout;
                $this.hover(function() {
                    window.clearTimeout(subTimeout);
                    $this.children('.dropdown-menu').show();

                    // Always close submenu siblings instantly
                    $this.siblings().children('.dropdown-menu').hide();
                }, function() {
                    var $submenu = $this.children('.dropdown-menu');
                    subTimeout = window.setTimeout(function() {
                        $submenu.hide();
                    }, settings.delay);
                });
            });
        });
    };

    $(document).ready(function() {
        // apply dropdownHover to all elements with the data-hover="dropdown" attribute
        $('[data-hover="dropdown"]').dropdownHover();
    });
})(jQuery, this);

样本标记:

<li class="dropdown">
    <a href="#" class="dropdown-toggle" data-toggle="dropdown" data-hover="dropdown" data-delay="1000" data-close-others="false">
        Account <b class="caret"></b>
    </a>
    <ul class="dropdown-menu">
        <li><a tabindex="-1" href="#">My Account</a></li>
        <li class="divider"></li>
        <li><a tabindex="-1" href="#">Change Email</a></li>
        <li><a tabindex="-1" href="#">Change Password</a></li>
        <li class="divider"></li>
        <li><a tabindex="-1" href="#">Logout</a></li>
    </ul>
</li>

如果它们小于平板电脑,这应该隐藏下拉式选项和它们的插入符号。

@media (max-width: 768px) {
    .navbar ul.dropdown-menu, .navbar li.dropdown b.caret {
        display: none;
    }
}

对于脱字号...我还没有看到任何指定完全阻止脱字符的简单CSS。

干得好:

.caret {
    display: none !important;
}

我使用了一些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();
});

我创建了一个基于最新(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>

Demo


我已经管理它如下:

$('ul.nav li.dropdown').hover(function(){
       $(this).children('ul.dropdown-menu').slideDown(); 
    }, function(){
       $(this).children('ul.dropdown-menu').slideUp(); 
});

我希望这可以帮助别人...


所以你有这个代码:

<a class="dropdown-toggle" data-toggle="dropdown">Show menu</a>

<ul class="dropdown-menu" role="menu">
    <li>Link 1</li>
    <li>Link 2</li> 
    <li>Link 3</li>                                             
</ul>

通常它在单击事件上工作,并且您希望它在悬停事件上工作。 这很简单,只需使用这个JavaScript / jQuery代码即可:

$(document).ready(function () {
    $('.dropdown-toggle').mouseover(function() {
        $('.dropdown-menu').show();
    })

    $('.dropdown-toggle').mouseout(function() {
        t = setTimeout(function() {
            $('.dropdown-menu').hide();
        }, 100);

        $('.dropdown-menu').on('mouseenter', function() {
            $('.dropdown-menu').show();
            clearTimeout(t);
        }).on('mouseleave', function() {
            $('.dropdown-menu').hide();
        })
    })
})

This works very well and here is the explanation: we have a button, and a menu. When we hover the button we display the menu, and when we mouseout of the button we hide the menu after 100 ms. If you wonder why I use that, is because you need time to drag the cursor from the button over the menu. When you are on the menu, the time is reset and you can stay there as many time as you want. When you exit the menu, we will hide the menu instantly without any timeout.

I've used this code in many projects, if you encounter any problem using it, feel free to ask me questions.


还增加了margin-top:0来重置.dropdown菜单的bootstrap css margin,这样当用户从下拉菜单缓慢地移动到菜单列表时,菜单列表不会消失。

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

.nav .dropdown-menu {
    margin-top: 0;
}

这会隐藏起来的

.navbar .dropdown-menu:before {
   display:none;
}
.navbar .dropdown-menu:after {
   display:none;
}

这对我有效:

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

这是内置Bootstrap 3的。只需将它添加到你的CSS:

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

这里有很多非常好的解决方案。 但我认为我会继续前进,并将其作为另一种选择放在这里。 这只是一个简单的jQuery代码片段,它可以像引导程​​序那样支持悬停而不是点击鼠标。 我只用版本3测试过,所以我不知道它是否可以与版本2一起工作。将它作为代码片段保存在你的编辑器中,并在一个关键帧处理它。

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

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


除了“我的头痛”(这很棒)的回答之外:

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

有两个悬而未决的问题:

  1. 点击下拉链接将打开下拉菜单。 它会保持打开状态,除非用户在其他地方点击,或者回过头来创建一个尴尬的用户界面。
  2. 下拉链接和下拉菜单之间有1px的余量。 这会导致下拉菜单在下拉菜单和下拉菜单之间缓慢移动时隐藏。

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

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

这也使您能够创建一个链接到您的父页面 - 这是默认实现不可能的。 您可以将“#”替换为要发送给用户的任何页面。

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

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






twitter-bootstrap