How to make Twitter Bootstrap menu dropdown on hover rather than click
Asked Answered
K

43

1248

I'd like to have my Bootstrap menu automatically drop down on hover, rather than having to click the menu title. I'd also like to lose the little arrows next to the menu titles.

Kaunas answered 16/1, 2012 at 9:36 Comment(6)
There is a solution for that, so mikko's answer is correct but covered now with a plugin for specifically that situation. bootstrap-hover-dropdownLambertson
See my newly published proper plugin which prevents the issues of the below CSS and js solutions, and works fine on iOS and on modern desktop browsers with touch events. Even the aria attributes are working fine with that: github.com/istvan-ujjmeszaros/bootstrap-dropdown-hoverGrane
I made a pure CSS3 dropdown with a bootstrap navbar check it out on CodePen Pure CSS3 DropdownPettish
Think twice if you really need it? Bootstrap is using for adaptive sites. It means they will be used on devices with touch controls as well. That's why it is designed this way. There is no "hover" on touch screens.Umbelliferous
Possible duplicate of Bootstrap Dropdown with HoverDisagreeable
Hi Serj.by But it is possible to achieve the same using media queries.Firooc
L
615

I created a pure on hover dropdown menu based on the latest (v2.0.2) Bootstrap framework that has support for multiple submenus and thought I'd post it for future users:

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

Lazar answered 13/4, 2012 at 14:46 Comment(8)
it's a design decision in bootstrap to do not open the dropdowns on hover event...Saltus
so good! I also removed class="dropdown-toggle" data-toggle="dropdown" so that only hovers, not click would trigger the menu. Note that when you're using responsive styles, the menus still get swept into the little button at top right, which is still triggered by a click. Big Thanks!Seamy
To avoid the auto drop down on smaller devices (such as phones) and aonly allow it as of a min-width of e.g. 768px do @media (min-width: 768px) {.dropdown-menu li:hover .sub-menu {visibility: visible;}} and @media (min-width: 768px) {.dropdown:hover .dropdown-menu {display: block;}}Fairfield
Also to make link with children clickable, you have to remove the "data-toggle='dropdown'" on <a> tag.Chamois
this is a long answer, just add .dropdown-menu li:hover .sub-menu { visibility: visible; } .dropdown:hover .dropdown-menu { display: block; }Mangosteen
Here is the solution for Bootstrap 4.x, with simple 7 lines of CSS code: bootsnipp.com/snippets/Vm7dZook
i have problem with this when there are 5-10 item with sub menu.all sub menu are fixed with top of the master element..Hobble
Thank you so much for the answer but below code is the only thing needed. .dropdown-menu li:hover .sub-menu { visibility: visible; } .dropdown:hover .dropdown-menu { display: block; }Karyolymph
G
924

To get the menu to automatically drop on hover then this can achieved using basic CSS. You need to work out the selector to the hidden menu option and then set it to display as block when the appropriate li tag is hovered over. Taking the example from the twitter bootstrap page, the selector would be as follows:

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

However, if you are using Bootstrap's responsive features, you will not want this functionality on a collapsed navbar (on smaller screens). To avoid this, wrap the code above in a media query:

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

To hide the arrow (caret) this is done in different ways depending on whether you are using Twitter Bootstrap version 2 and lower or version 3:

Bootstrap 3

To remove the caret in version 3 you just need to remove the HTML <b class="caret"></b> from the .dropdown-toggle anchor element:

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

Bootstrap 2 & lower

To remove the caret in version 2 you need a little more insight into CSS and I suggest looking at how the :after pseudo element works in more detail. To get you started on your way to understanding, to target and remove the arrows in the twitter bootstrap example, you would use the following CSS selector and code:

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

It will work in your favour if you look further into how these work and not just use the answers that I have given you.

Thanks to @CocaAkat for pointing out that we were missing the ">" child combinator to prevent sub menus being shown on the parent hover

Golda answered 16/1, 2012 at 10:26 Comment(23)
Also had to add margin: 0;, otherwise the 1px margin above .dropdown-menu causes buggy behavior.Ancient
Simple solution, but the parent link is still not clickable. I'm using latest bootstrap with roots theme.Hendren
Note: Yes it does - this will work in any browser that twitter bootstrap supports. @GeorgeEdison This is basic CSS - what part would not be supported by IE8? If you are having problems, post a question, not misleading comments.Golda
@MyHeadHurts: After some further research - turns out this was indeed a Bootstrap bug and it was only fixed five days ago.Merwyn
For bootstrap 2.1 the first css selector should now be: ul.nav li.dropdown-toggle:hover ul.dropdown-menu { display: block; }Keratogenous
@DDL449 I don't think it is possible for mods to accept answers on behalf of other people. Luckily the voting system in StackOverflow is a good way to show what the good answers are - which also works well when answers (which are not always the best) are marked as the accepted answer.Golda
There is a problem with this approach in that there is a slight gap between the dropdown menu and the actual menu item so if you move slowly it will close the coverAndri
@ArchimedesTrajano the first comment by SalmanPK shows the solution to fix this. If this does not resolve the problem then let me know and I will revisit the answer as Twitter Bootstrap is always being updatedGolda
@Hendren Use this jquery plugin for Bootstrap NavBar support hover on specific screen size and clickable on specific screen size.Arrow
Opening the dropdown on hover seems awkward a collapsing responsive navbar is in the collapsed state. Enclosing the CSS suggested by MyHeadHurts within a media query that only allows the rule when the width of the window is greater than the width required before the navigation collapses seems to help. /* Make dropdowns activate on hover except when navigation is collapsed by max-width */ @media (min-width: 979px) { ul.nav li.dropdown:hover > ul.dropdown-menu { display: block; } }Whacky
@CharlesHamel can you add a JSFiddle demostrating the code "not working" (with an explanation of what is happening and what you are expecting to happen) and I will take a look. I have had a quick look at the CSS classes in Bootstrap 3.0 and they look to be the same - the only change is the way the caret is displayed so I have updated my answer to reflect this!Golda
@Hendren to be able to click the link, you must remove the data-toggle="dropdown" attribute.Christoffer
One small issue with this solution is that the dropdown menu stays open after clicking on a menu item (until the cursor is moved).Sidesaddle
@Sidesaddle - that sounds like something caused by Javascript. Could you put together a JSFiddle reporducing the issue and I will take a lookGolda
@My Head Hurts - you're right, I'm unable to reproduce this in a simple example.Sidesaddle
I added this css class to make the menu item have a hover over color. .navbar-nav > li.dropdown:hover { background-color: gray ; }Retrench
@Sidesaddle - i have the same problem, did you find the cause?Milium
@My Head Hurts found this which looks like the same problem: bootsnipp.com/snippets/featured/…Milium
@Milium - In general, if you come across an issue it is better to open a new question as it will help other visitors and will more likely get your question answered. The code you linked to uses a javascript solution rather than a CSS based solution, which means it is unlikely to share behaviours with this solution. In fact, from quickly looking at the code in the linked example, the problem looks to be in the way the author uses the toggle function.Golda
I think it's important that you bring up that this is not recommended on small screens. On a smartphone, a user would not be able to trigger the hover event because they can't hover with their finger.Rugen
I've added this solution to my website, however scrollspy is not working now. Can anyone help me with that ? #43854314Peat
This doesn't work well on touch/mobile devices. After clicking the menu the menu indeed opens, but you cannot click the menu again to close it. You have to tap somewhere else in the screen to close it, which, on Chrome-iOS at least, causes a flickering effect.Falster
In Bootstrap 4 it has changed, the proper code is div.dropdown instead of ul.dropdown for example: @media (min-width: 992px) { ul.nav li.dropdown:hover > div.dropdown-menu { display: block; } }Hoebart
L
615

I created a pure on hover dropdown menu based on the latest (v2.0.2) Bootstrap framework that has support for multiple submenus and thought I'd post it for future users:

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

Lazar answered 13/4, 2012 at 14:46 Comment(8)
it's a design decision in bootstrap to do not open the dropdowns on hover event...Saltus
so good! I also removed class="dropdown-toggle" data-toggle="dropdown" so that only hovers, not click would trigger the menu. Note that when you're using responsive styles, the menus still get swept into the little button at top right, which is still triggered by a click. Big Thanks!Seamy
To avoid the auto drop down on smaller devices (such as phones) and aonly allow it as of a min-width of e.g. 768px do @media (min-width: 768px) {.dropdown-menu li:hover .sub-menu {visibility: visible;}} and @media (min-width: 768px) {.dropdown:hover .dropdown-menu {display: block;}}Fairfield
Also to make link with children clickable, you have to remove the "data-toggle='dropdown'" on <a> tag.Chamois
this is a long answer, just add .dropdown-menu li:hover .sub-menu { visibility: visible; } .dropdown:hover .dropdown-menu { display: block; }Mangosteen
Here is the solution for Bootstrap 4.x, with simple 7 lines of CSS code: bootsnipp.com/snippets/Vm7dZook
i have problem with this when there are 5-10 item with sub menu.all sub menu are fixed with top of the master element..Hobble
Thank you so much for the answer but below code is the only thing needed. .dropdown-menu li:hover .sub-menu { visibility: visible; } .dropdown:hover .dropdown-menu { display: block; }Karyolymph
A
236

In addition to the answer from "My Head Hurts" (which was great):

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

There are 2 lingering issues:

  1. Clicking on the dropdown link will open the dropdown-menu. And it will stay open unless the user clicks somewhere else, or hovers back over it, creating an awkward UI.
  2. There is a 1px margin between the dropdown link, and dropdown-menu. This causes the dropdown-menu to become hidden if you move slowly between the dropdown and dropdown-menu.

The solution to (1) is removing the "class" and "data-toggle" elements from the nav link

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

This also gives you the ability to create a link to your parent page - which wasn't possible with the default implementation. You can just replace the "#" with whatever page you want to send the user.

The solution to (2) is removing the margin-top on the .dropdown-menu selector

.navbar .dropdown-menu {
    margin-top: 0px;
}
Amye answered 24/2, 2012 at 18:0 Comment(8)
To fix the deliberate click, I just removed the data-toggle="dropdown" attribute, which seemed to work.Gustie
Solution (2) for nav-pill buttons: .nav-pills .dropdown-menu { margin-top: 0px; }Oddfellow
To fix the problem I noted above li.dropdown:hover > ul.dropdown-menuAndri
I had to add an !important to effectively solve (2).Padang
For issue (2), add a transparent border-top instead of the margin-top to keep any intended spacing as well as fixing the ::hover issue.Lintwhite
removing "class" and "data-toggle" attributes from nav links make it stop working fine in mobile and tablets :(Anchoress
if we remove "class" and "data-toggle" elements from the nav link as the solution for for problem 1, how can we make it run on mobile devices?? please helpGyp
If you removed the data-toggle="dropdown" attribute, you won't be able to expand the drop down menu using the keyboard. So it will not be 508 compliant. How can you disable the click but keep the keyboard functionality?Retrench
G
136

I've used a bit of 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();
});
Groats answered 22/5, 2012 at 17:49 Comment(6)
Like this. Am using JQuery anyway with the Bootstrap stuff and still allows for the default 'click' functionality in touchscreen devices.Adiell
Used this. I like that it still allows the click functionality as well, for mobiles, but for desktops the hover is perfect.Saint
I used this but also extended it to be useable for dropdowns that are not in a nav. I add class dropdown-hover to the btn-group div and used this jQuery finder $('ul.nav li.dropdown, .dropdown-hover').hover(function() {. Thanks!Sawfly
Used this one, nice and small. The css version did not allow submenu to stay displayed, and 200ms was too quick so I changed it to $('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); }); }); : When the submenu is hover stop fadeOutApiary
this doesn't seem to work with jqLite that is included with anguraljsSakovich
@nuander, this was intended for Bootstrap V1/2 ::: So this solution is not relevant anymore :::Groats
R
78

Simply customize your CSS style in three lines of code

.dropdown:hover .dropdown-menu {
   display: block;
}
Randell answered 5/4, 2014 at 6:24 Comment(0)
P
72

There are a lot of really good solutions here. But I thought that I would go ahead and put mine in here as another alternative. It's just a simple jQuery snippet that does it the way bootstrap would if it supported hover for dropdowns instead of just click. I've only tested this with version 3 so I don't know if it would work with version 2. Save it as a snippet in your editor and have it at the stroke of a key.

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

Basically, It's just saying when you hover on the dropdown class, it will add the open class to it. Then it just works. When you stop hovering on either the parent li with the dropdown class or the child ul/li's, it removes the open class. Obviously, this is only one of many solutions, and you can add to it to make it work on only specific instances of .dropdown. Or add a transition to either parent or child.

Platinotype answered 31/1, 2014 at 17:28 Comment(5)
Great solution! I also removed data-toggle="dropdown" attribute from link in order to make top link clickable.Fidole
That's a good tip Sergey. I always make sure the top link goes nowhere so that it works on tablets and phones as well.Platinotype
@Fidole I wouldn't recommend doing that. You would break the functionality for mobile users. They can't use the hover function to open a menu and need to be able to click it.Chenille
This looks really good. Any idea how to add a bit of animation using CSS transitions?Myongmyopia
In Bootstrap 4 you can get the same result by finding a child element with the dropdown-menu class and using the show class toggle:function(){ $(this).find(".dropdown-menu").addClass('show') }, function(){ $(this).find(".dropdown-menu").removeClass('show') }Otolaryngology
F
25

If you have an element with a dropdown class like this (for example):

<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>

Then you can have the dropdown menu to be automatically drop down on hover over, rather than having to click its title, by using this snippet of jQuery code:

<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>

Here is a demo

This answer relied on @Michael answer, I have made some changes and added some additions to get the dropdown menu work properly

Fugato answered 27/9, 2014 at 21:13 Comment(0)
W
22

[Update] The plugin is on GitHub and I am working on some improvements (like use only with data-attributes (no JS necessary). I've leaving the code in below, but it's not the same as what's on GitHub.

I liked the purely CSS version, but it's nice to have a delay before it closes, as it's usually a better user experience (i.e. not punished for a mouse slip that goes 1 px outside the dropdown, etc), and as mentioned in the comments, there's that 1px of margin you have to deal with or sometimes the nav closes unexpectedly when you're moving to the dropdown from the original button, etc.

I created a quick little plugin that I've used on a couple sites and it's worked nicely. Each nav item is independently handled, so they have their own delay timers, etc.

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

The delay parameter is pretty self explanatory, and the instantlyCloseOthers will instantly close all other dropdowns that are open when you hover over a new one.

Not pure CSS, but hopefully will help someone else at this late hour (i.e. this is an old thread).

If you want, you can see the different processes I went through (in a discussion on the #concrete5 IRC) to get it to work via the different steps in this gist: https://gist.github.com/3876924

The plugin pattern approach is much cleaner to support individual timers, etc.

See the blog post for more.

Works answered 12/10, 2012 at 3:2 Comment(0)
M
21

This worked for me:

.dropdown:hover .dropdown-menu {
    display: block;
}
Mottle answered 6/10, 2015 at 11:47 Comment(2)
With mobile however - it is strange.Engadine
The margin between menu and dropdown-menu makes this useless.Soporific
P
16

This is built into Bootstrap 3. Just add this to your CSS:

.dropdown:hover .dropdown-menu {
    display: block;
}
Purcell answered 18/11, 2017 at 20:23 Comment(0)
U
11

Just want to add, that if you have multiple dropdowns (as I do) you should write:

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

And it'll work properly.

Unwashed answered 31/10, 2012 at 20:22 Comment(1)
My .dropdown-menu had margin: 2px 0 0; which meant a slow mouseEnter from above hid the menu prematurely. ul.dropdown-menu{ margin-top: 0; }Brechtel
S
10

Even better with 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');
});
Saltus answered 17/8, 2012 at 1:51 Comment(2)
I changed your code to 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'); }); so the submenu won't be displayed on hover.Meilhac
This code won't work anymore with the latest releases.Chenille
H
9

The best way of doing it is to just trigger Bootstrap's click event with a hover. This way, it should still remain touch device friendly.

$('.dropdown').hover(function(){ 
  $('.dropdown-toggle', this).trigger('click'); 
});
Huttan answered 1/3, 2014 at 8:52 Comment(2)
Unwanted result: mousein, click and mouseout will leave the menu open. This is not what I want...Gav
Using this, It run the bootstrap function to open the dropdown, That function does many other things, like aria-expanded="true"Steven
P
9

You can use the default $().dropdown('toggle') method to toggle the dropdown menu on hover:

$(".nav .dropdown").hover(function() {
  $(this).find(".dropdown-toggle").dropdown("toggle");
});
Paratuberculosis answered 23/9, 2015 at 8:47 Comment(0)
C
8

In my opinion the best way is like this:

;(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);

Sample markup:

<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>
Crew answered 10/9, 2013 at 9:53 Comment(1)
This is Cameron Spear's work, thought I'd give him the shoutout: cameronspear.com/blog/bootstrap-dropdown-on-hover-pluginChough
F
8

I've managed it as follows:

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

I hope this helps someone...

Flora answered 30/9, 2013 at 14:35 Comment(0)
J
7

This also can do that.


$('.dropdown').on('mouseover',function(){
    $(this).find('.dropdown-menu').show();
});
$('.dropdown').on('mouseleave',function(){
    $(this).find('.dropdown-menu').hide();
});

If the dropdown has a gap between the hovered element the drop down will immediately close as seen in this GIF

Dropdown hiding as soon as the element is cleared

To prevent this behaviour you can add a timeout to the events of 100 ms

let dropdownTimer;
$('.dropdown').on('mouseover', () => {
    clearTimeout(dropdownTimer)
    $(this).find('.dropdown-menu').show();
});
$('.dropdown').on('mouseleave', () =>{
    dropdownTimer = setTimeout(() => {
        $(this).find('.dropdown-menu').hide();
    }, 100)
});

Dropdown holding open for a set timeout

Jeniferjeniffer answered 28/7, 2020 at 11:43 Comment(0)
V
6

This is probably a stupid idea, but to just remove the arrow pointing down, you can delete the

<b class="caret"></b>

This does nothing for the up pointing one, though...

Vladamar answered 27/2, 2012 at 18:1 Comment(0)
E
6

I have published a proper plugin for the Bootstrap 3 dropdown hover functionality, in which you can even define what happens when clicking on the dropdown-toggle element (the click can be disabled):

https://github.com/istvan-ujjmeszaros/bootstrap-dropdown-hover


Why I made it when there are many solutions already?

I had issues with all the previously existing solutions. The simple CSS ones are not using the .open class on the .dropdown, so there will be no feedback on the drop-down toggle element when the drop-down is visible.

The js ones are interfering with clicking on .dropdown-toggle, so the dropdown shows up on hover, then hides it when clicking on an opened drop-down, and moving out the mouse will trigger the drop-down to show up again. Some of the js solutions are breaking iOS compatibility, some plugins are not working on modern desktop browsers which are supporting the touch events.

That's why I made the Bootstrap Dropdown Hover plugin which prevents all these issues by using only the standard Bootstrap javascript API, without any hack. Even the Aria attributes are working fine with this plugin.

Ezequiel answered 27/6, 2015 at 3:13 Comment(3)
What's your opinion about github.com/vadikom/smartmenus ? I cannot decide, both libraries seem to be really good.Chas
Smartmenus looks really good, it may be better for menus. My plugin is just a small addition to the bootstrap dropdowns, it does no more than opening a dropdown on hover, while smartmenu supports submenus as well, and does some other fancy things.Grane
Thanks. I see that smartmenu's code is very extensive and there's also a lot of CSS. So far I went with bootstrap-dropdown-hover, because it seems to do the job and more compact. I'm building a landing site with left side navbar.Chas
C
5

Also added margin-top:0 to reset the bootstrap css margin for .dropdown-menu so the menu list dosen't dissapear when the user hovers slowly from drop down menu to the menu list.

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

.nav .dropdown-menu {
    margin-top: 0;
}
Choragus answered 14/5, 2014 at 12:5 Comment(1)
this is the correct answer, bootstrap is ready for hover on dropdown, if the mouse doesn't go outside of dropdown menu. Removing margin-top allow to go from link to menu without break and so without auto-close of the menu. And this solution allow to keep the correct behavior for touch devicesCorves
S
5

This works for Bootstrap V4

JS:

<script>
        $(function() {
            $('.dropdown-hover').hover(
                function() { $(this).addClass('show'); $(this).find('[data-toggle="dropdown"]').attr('aria-expanded', true); $(this).find('.dropdown-menu').addClass('show'); },
                function() { $(this).removeClass('show'); $(this).find('[data-toggle="dropdown"]').attr('aria-expanded',false); $(this).find('.dropdown-menu').removeClass('show'); }
            );
        });
    </script>

Vanilla Bootstrap 4 Dropdown HTML except for the addition of the dropdown-hover class:

<div class="dropdown dropdown-hover">
<button class="btn btn-text dropdown-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
    ABOUT
</button>
<div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
    <a class="dropdown-item" href="#">Action</a>
    <a class="dropdown-item" href="#">Another action</a>
    <a class="dropdown-item" href="#">Something else here</a>
</div>

If you don't want to selectively enable the hover feature by using the .dropdown-hover class then simply change the jquery selector from .dropdown-hover to .dropdown.

Synchrocyclotron answered 20/2, 2019 at 22:51 Comment(0)
M
4

Use this code to open the submenu on mousehover (desktop only):

$('ul.nav li.dropdown').hover(function () {
    if ($(window).width() > 767) {
        $(this).find('.dropdown-menu').show();
    }
}, function () {
    if ($(window).width() > 767) {
        $(this).find('.dropdown-menu').hide().css('display','');
    }
});

And if you want the first level menu to be clickable, even on mobile add this:

    $('.dropdown-toggle').click(function() {
    if ($(this).next('.dropdown-menu').is(':visible')) {
        window.location = $(this).attr('href');
    }
});

The submenu (dropdown-menu) will be opened with mousehover on desktop, and with click/touch on mobile and tablet. Once the submenu was open, a second click will let you open the link. Thanks to the if ($(window).width() > 767), the submenu will take the full screen width on mobile.

Mope answered 26/10, 2016 at 12:52 Comment(2)
I'd like to use your code, but I'm having trouble getting it to work correctly. First, how to remove the hover() for mobile and only use that for desktop? When I use your code, and resize the window to mobile, I get both the hover() and click() functionality. But even more strange... is that this behavior will stop When I refresh the browser, ha! Could you show me how to fix this? I need desktop submenus to show on hover() and click()to show submenus on mobile Without having to refresh the browser even when resizing the window to work properly. I hope this is clearNicol
Use this best method: @KaunasSteven
H
4
$('.dropdown').hover(function(e){$(this).addClass('open')})
Healall answered 14/2, 2017 at 13:27 Comment(1)
Please provide some details to your answer.Torbart
E
4

Bootstrap versions 4 and 5 solutions. (IE compatible)

These are complete solutions that use the mouseover and mouseleave events and some screen width checking. This is better than a pure CSS solution.

Bootstrap v5 - Pure JS (intended for webpack)

export class BootstrapOpenMenuHover {

/**
 * Constructor.
 */
constructor() {
  this.windowWidth = window.innerWidth;
  this.mobileBreakPoint = 991; // Put your menu break point here, when it switches to a hamburger icon.
  this.dropdownNavItems = document.querySelectorAll(".dropdown-toggle.nav-link");
  this.dropdownMenuItems = document.querySelectorAll(".dropdown-menu");

  this.setEventListeners();
}

/**
 * Set all of our event listeners.
 */
setEventListeners() {
  const _self = this;

  // To be safe set the width once the dom is loaded.
  window.addEventListener('load',  function () {
    _self.windowWidth = window.innerWidth;
  });

  // Keep track of the width in the event of a resize.
  window.addEventListener('resize',  function () {
    _self.windowWidth = window.innerWidth;
  });

  // Bind our hover events.
  if (_self.dropdownNavItems !== null)  {
    for (let i = 0; i < _self.dropdownNavItems.length; i++) {

      // On mouse enter.
      _self.dropdownNavItems[i].addEventListener('mouseenter', function () {
        if (_self.windowWidth >= _self.mobileBreakPoint) {
          this.classList.add('show');
          this.ariaExpanded = true;
          this.dataset.bsToggle = null;

          // Update the .dropdown-menu
          this.nextElementSibling.classList.add('show');
          this.nextElementSibling.dataset.bsPopper = 'none';
        }
      });

      // On mouse leave.
      _self.dropdownNavItems[i].addEventListener('mouseleave', function () {
        if (_self.windowWidth >= _self.mobileBreakPoint) {
          this.classList.remove('show');
          this.ariaExpanded = false;
          this.dataset.bsToggle = 'dropdown';

          // Update the .dropdown-menu
          this.nextElementSibling.classList.remove('show');
          this.nextElementSibling.dataset.bsPopper = null;
        }
      });
    }
  }

  // Bind events to .dropdown-menu items.
  if (_self.dropdownMenuItems !== null) {
    for (let i = 0; i < _self.dropdownMenuItems.length; i++) {
      // On mouse enter.
      _self.dropdownMenuItems[i].addEventListener('mouseenter', function () {
        if (_self.windowWidth >= _self.mobileBreakPoint) {
          this.classList.add('show');
          this.dataset.bsPopper = 'none';

          // Update the .dropdown-toggle
          this.previousElementSibling.classList.add('show');
          this.previousElementSibling.ariaExpanded = true;
          this.previousElementSibling.dataset.bsToggle = null;
        }
      });

      // On mouse leave.
      _self.dropdownMenuItems[i].addEventListener('mouseleave', function () {
        if (_self.windowWidth >= _self.mobileBreakPoint) {
          this.classList.remove('show');
          this.dataset.bsPopper = null;

          // Update the .dropdown-toggle
          this.previousElementSibling.classList.remove('show');
          this.previousElementSibling.ariaExpanded = false;
          this.previousElementSibling.dataset.bsToggle = 'dropdown';
        }
      });
    }
   }
  }
 }

 const bootstrapOpenMenuHover = new BootstrapOpenMenuHover();

Bootstrap v4 Solution

This will allow you to follow top level navigation links.

This was built with desktop and mobile in mind. Fell free to change the BREAK_POINT variable to suit your needs :D.

jQuery

var WINDOW_WIDTH;
var BREAK_POINT = 991;

(function ($) {

    /** Set window width onload */
    WINDOW_WIDTH = $(window).width(); // Returns width of browser viewport
    /** Set window width if the browser is resized */
    $(window).resize(function () {
        WINDOW_WIDTH = $(window).width(); // Returns width of browser viewport
    });

    /** Dropdown menu on mouseenter */
    $(".nav-item.dropdown").on('mouseenter', function () {
        console.log("mouseenter");
        if (WINDOW_WIDTH >= BREAK_POINT) {
            // Open up the dropdown
            $(this).addClass('show'); // add the class show to the li parent
            $(this).children('.nav-link').removeAttr('data-toggle'); // remove the data-toggle attribute so we can click and follow link
            $(this).children('.dropdown-menu').addClass('show'); // add the class show to the dropdown div sibling
        }
    });
    /** Dropdown menu on mouseleave */
    $(".nav-item.dropdown").on('mouseleave', function () {
        console.log("mouseleave");
        if (WINDOW_WIDTH >= BREAK_POINT) {
            // Close the dropdown
            $(this).removeClass('show'); // add the class show to the li parent
            $(this).children('.nav-link').attr('data-toggle', 'dropdown'); // remove the data-toggle attribute so we can click and follow link
            $(this).children('.dropdown-menu').removeClass('show'); // add the class show to the dropdown div sibling
        }
    });
});

CSS

@media(min-width:  768px) {
  .dropdown-menu {
    margin-top: 0; // fixes closing on slow mouse transition
  }
}
Engadine answered 19/7, 2018 at 16:37 Comment(2)
Kash's solution works with bootstrap 4. This JS is unnecessaryGastrostomy
@Gastrostomy Sorry but I found that if you want to be able to still follow top level navigation links this is the way to go. Using a pure css solution won't allow you to follow top lvl navigation clicks on desktop. Hope that makes sense.Engadine
E
4

The very simple solution for version 2, only CSS. Keeps the same friendly functionality for mobile and tablet.

@media (min-width: 980px) {
    .dropdown:hover .dropdown-menu {
       display: block;
    }
}
Edra answered 30/8, 2018 at 9:41 Comment(1)
This doesn't work great for some themes where there is a gap between the menu item and the dropdown. The menu will disappear when the mouse moves into this gap.Capriole
S
3

This should hide the drop downs and their carets if they are smaller than a tablet.

@media (max-width: 768px) {
    .navbar ul.dropdown-menu, .navbar li.dropdown b.caret {
        display: none;
    }
}
Secularity answered 27/3, 2012 at 17:53 Comment(1)
Why would you want to hide it? Now the mobile users have no way to access the links that are in the submenu. It's better to turn the hover effect off on a mobile device and keep the dropdown menu intact. That way they can open it by clicking on it.Chenille
W
3

This will hide the up ones

.navbar .dropdown-menu:before {
   display:none;
}
.navbar .dropdown-menu:after {
   display:none;
}
Worsen answered 11/4, 2012 at 16:26 Comment(0)
C
3

The jQuery solution is good, but it will need to either deal with on click events (for mobile or tablet) as hover won't work properly... Could maybe do some window re-size detection?

Andres Ilich's answer seems to work well, but it should be wrapped in a media query:

@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;
    }
}
Cofsky answered 11/1, 2013 at 7:1 Comment(0)
L
3

So you have this code:

<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>

Normally it works on a click event, and you want it work on a hover event. This is very simple, just use this JavaScript/jQuery code:

$(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.

Lewan answered 12/3, 2014 at 13:33 Comment(0)
P
3

For the caret... I haven't seen any one specifying simple CSS that totally blocks the caret.

Here you go:

.caret {
    display: none !important;
}
Paulownia answered 7/1, 2015 at 10:29 Comment(0)
C
3

Here is the JSFiddle -> https://jsfiddle.net/PRkonsult/mn31qf0p/1/

The JavaScript bit at the bottom is what does the actual magic.

HTML

<!--http://getbootstrap.com/components/#navbar-->
<div class="body-wrap">
  <div class="container">
    <nav class="navbar navbar-inverse" role="navigation">
      <div class="container-fluid">
        <!-- Brand and toggle get grouped for better mobile display -->
        <div class="navbar-header">
          <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
            <span class="sr-only">Toggle navigation</span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
          </button>
          <a class="navbar-brand" href="#">Brand</a>
        </div>

        <!-- Collect the nav links, forms, and other content for toggling -->
        <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
          <ul class="nav navbar-nav">
            <li class="active"><a href="#">Link</a></li>
            <li><a href="#">Link</a></li>
            <li class="dropdown">
              <a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown <b class="caret"></b></a>
              <ul class="dropdown-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><a href="#">Separated link</a></li>
                <li class="divider"></li>
                <li><a href="#">One more separated link</a></li>
              </ul>
            </li>
          </ul>

          <ul class="nav navbar-nav navbar-right">
            <li><a href="#">Link</a></li>
            <li class="dropdown">
              <a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown <b class="caret"></b></a>
              <ul class="dropdown-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><a href="#">Separated link</a></li>
              </ul>
            </li>
          </ul>
        </div>
        <!-- /.navbar-collapse -->
      </div>
      <!-- /.container-fluid -->
    </nav>
  </div>
</div>

CSS

/* Bootstrap dropdown hover menu */

body {
  font-family: 'PT Sans', sans-serif;
  font-size: 13px;
  font-weight: 400;
  color: #4f5d6e;
  position: relative;
  background: rgb(26, 49, 95);
  background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, rgba(26, 49, 95, 1)), color-stop(10%, rgba(26, 49, 95, 1)), color-stop(24%, rgba(29, 108, 141, 1)), color-stop(37%, rgba(41, 136, 151, 1)), color-stop(77%, rgba(39, 45, 100, 1)), color-stop(90%, rgba(26, 49, 95, 1)), color-stop(100%, rgba(26, 49, 95, 1)));
  filter: progid: DXImageTransform.Microsoft.gradient(startColorstr='#1a315f', endColorstr='#1a315f', GradientType=0);
}

.body-wrap {
  min-height: 700px;
}

.body-wrap {
  position: relative;
  z-index: 0;
}

.body-wrap: before,
.body-wrap: after {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: -1;
  height: 260px;
  background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, rgba(26, 49, 95, 1)), color-stop(100%, rgba(26, 49, 95, 0)));
  background: linear-gradient(to bottom, rgba(26, 49, 95, 1) 0%, rgba(26, 49, 95, 0) 100%);
  filter: progid: DXImageTransform.Microsoft.gradient(startColorstr='#1a315f', endColorstr='#001a315f', GradientType=0);
}

.body-wrap:after {
  top: auto;
  bottom: 0;
  background: linear-gradient(to bottom, rgba(26, 49, 95, 0) 0%, rgba(26, 49, 95, 1) 100%);
  filter: progid: DXImageTransform.Microsoft.gradient(startColorstr='#001a315f', endColorstr='#1a315f', GradientType=0);
}

nav {
  margin-top: 60px;
  box-shadow: 5px 4px 5px #000;
}

Then the important bit of JavaScript code:

$('ul.nav li.dropdown').hover(function() {
  $(this).find('.dropdown-menu').stop(true, true).delay(200).fadeIn(500);
}, function() {
  $(this).find('.dropdown-menu').stop(true, true).delay(200).fadeOut(500);
});
Collodion answered 14/8, 2016 at 11:15 Comment(0)
S
3

The most Standard Answer:

  • Supports aria-expanded attribute
  • Supports non touch devices
  • Supports touch devices
  • Supports all dropdowns
var isTouchDevice = (('ontouchstart' in window) ||
                                (navigator.MaxTouchPoints > 0) ||
                                (navigator.msMaxTouchPoints > 0));
if(!isTouchDevice){
    // open dropdowns on hover on non mobile devices
    $(".dropdown").hover(function(e) {
        $('.dropdown-toggle', this).dropdown("toggle");
        e.stopPropagation();
    });
    // prevent blinkling
    $(".submenu-link").click(function(e) {
        e.stopPropagation();
    });
}

You can change $(".dropdown") to a specific area if you need:

$("#top-menu .dropdown")
Steven answered 25/7, 2017 at 9:42 Comment(2)
This wouldn't allow the navbar .dropdown-toggle elements to function as normal links.Gigantes
@Gigantes Try this new method !Steven
A
2

This works for WordPress Bootstrap:

.navbar .nav > li > .dropdown-menu:after,
.navbar .nav > li > .dropdown-menu:before {
    content: none;
}
Anaphora answered 15/3, 2013 at 18:34 Comment(0)
N
2

Overwrite bootstrap.js with this script.

jQuery(document).ready(function ($) {
$('.navbar .dropdown').hover(function() {
    $(this).addClass('extra-nav-class').find('.dropdown-menu').first().stop(true, true).delay(250).slideDown();
}, function() {
    var na = $(this)
    na.find('.dropdown-menu').first().stop(true, true).delay(100).slideUp('fast', function(){ na.removeClass('extra-nav-class') })
});

$('.dropdown-submenu').hover(function() {
    $(this).addClass('extra-nav-class').find('.dropdown-menu').first().stop(true, true).delay(250).slideDown();
}, function() {
    var na = $(this)
    na.find('.dropdown-menu').first().stop(true, true).delay(100).slideUp('fast', function(){ na.removeClass('extra-nav-class') })
});

}); 
Necrosis answered 22/1, 2014 at 5:53 Comment(0)
F
2

Here's my technique that adds a slight delay before the menu is closed after you stop hovering on the menu or the toggle button. The <button> that you would normally click to display the nav menu is #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);
});
Freehold answered 18/2, 2014 at 19:43 Comment(0)
N
2

To enhance Sudharshan's answer, I wrap this in a media query to prevent the hover when on XS display widths...

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

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

Also the caret in the markup is not required, just the dropdown class for the li.

Nupercaine answered 26/2, 2015 at 3:30 Comment(0)
R
2

Bootstrap 4, 2019

I read a lot of these answers but I ended up doing it myself because it was just not what i needed.

I have Bootstrap 4, and want to keep the click + the hover functionality. Besides I want to enable it only on dropdowns that have an extra class ".open-on-hover".

I also want to keep the Bootstrap's Jquery that positions the dropdown when it is next to the edge of the page. So we don't just want to do "display: block". We want the full Bootstrap's way of working. So I just trigger click.

The logic is "If it is a mouseenter then open it, if it is a mouseleave then hide it if it is open"

/**
 * Open Bootstrap 4 dropdown on hover
 */
$(document).on('mouseenter mouseleave', '.dropdown.open-on-hover', function(e) 
{
    let toggler = $(this).find('[data-toggle="dropdown"]').first();

    if(e.type === 'mouseenter') {
        $(toggler).trigger('click', 'open');
    } else if ($(this).children('.dropdown-menu.show').length) {
        $(toggler).trigger('click', 'close');
    }
});

The html

<div class="dropdown open-on-hover">
    <div class="btn" data-toggle="dropdown">
        Hover or click me
    </div>
    <div class="dropdown-menu">
        <a class="dropdown-item">
            Item 1
        </a>
        <a class="dropdown-item">
            Item 2
        </a>
    </div>
</div>
Residual answered 6/8, 2019 at 8:3 Comment(0)
G
1

We saw, In addition to the answer from "My Head Hurts", "Cory Price" found out two problems:

Problem 1: Clicking on the dropdown link will open the dropdown-menu. And it will stay open unless the user clicks somewhere else, or hovers back over it, creating an awkward UI.

Solution: Remove the "class" and "data-toggle" elements from the nav link

The solution was nearly perfect, but the problem here is, when it comes to mobile devices and tablets, it won't work!

I'm using a bit of jQuery code to fix this..

if ($(window).width() > 769) {
    $('.dropdown-toggle').removeAttr('data-toggle');
    $('.dropdown-menu').removeAttr('style');
    $('.dropdown').removeClass('open');
}
$(window).resize(function () {
    if ($(window).width() > 769) {
        $('.dropdown-toggle').removeAttr('data-toggle');
        $('.dropdown-menu').removeAttr('style');
        $('.dropdown').removeClass('open');
    }
    else {
        $('.dropdown-toggle').attr("data-toggle", "dropdown");
    }
});

Note: Here we assume that the collapse to mobile devices and tablets is from 768px.

Gyp answered 4/9, 2014 at 11:37 Comment(1)
This is not a good idea as many touch devices have viewports the same size or larger than desktop and laptop devices. Better to use a touch detection that works for IOS, Android, and Windows Mobile or just stay with clicks.Switchblade
M
1

Use two links inline. Hide the link with the dropdown toggle and add the onmouseover event over the visible link to click the dropdown menu.

<a class="pretty-button"
   href="#" alt="Notifications"
   onmouseover="$('#notifications-dropdown').click()">
</a>

<a style="display:none"
   id="notifications-dropdown"
   class="js-nav js-tooltip js-dynamic-tooltip"
   href="#"
   alt="Notifications"
   data-toggle="dropdown">
   <span class="fa fa-flag fa-2x"></span>
</a>
Magnus answered 2/2, 2015 at 17:46 Comment(0)
G
1

I hope this helps. Check the link https://jsfiddle.net/awb7gfb1/

<nav>
    <div id="menubar" class=" collapse navbar-collapse row">
        <ul id="dropdownNavbar" class="nav navbar-nav">
            <li class="dropdown">
                <button type="button" class="btn btn-primary dropbtn"><span class="glyphicon glyphicon-time"></span>
                Time Card
                <span class="caret"></span></button>
                <div class="dropdown-content">
                    <a id="showTimeCard" href="#">My Time Card</a>
                    <a href="#">Sub Menu 2</a>
                    <a href="#">Sub Menu 3</a>
                    <a href="#">Sub Menu 4</a>
                    <a href="#">Sub Menu 5</a>
                </div>
            </li>
            <li class="dropdown">
                <button type="button" class="btn btn-primary dropbtn"><span class="glyphicon glyphicon-stats"></span>
                Project
                <span class="caret"></span></button>
                <div class="dropdown-content">
                    <a href="#">Sub Menu 1</a>
                    <a href="#">Sub Menu 2</a>
                    <a href="#">Sub Menu 3</a>
                </div>
            </li>
            <li class="dropdown">
                <button type="button" class="btn btn-primary dropbtn"><span class="glyphicon glyphicon-user"></span>
                HR Links
                <span class="caret"></span></button>
                <div class="dropdown-content">
                    <a href="#">Sub Menu 1</a>
                    <a href="#">Sub Menu 2</a>
                </div>
            </li>
            <li class="dropdown">
                <button type="button" class="btn btn-primary dropbtn">
                <span class="glyphicon glyphicon-screenshot"></span>
                Leave Tracker
                <span class="caret"></span></button>
                <div class="dropdown-content">
                    <a href="#">Sub Menu 1</a>
                    <a href="#">Sub Menu 2</a>
                    <a href="#">Sub Menu 3</a>
                    <a href="#">Sub Menu 4</a>
                </div>
            </li>
            <li class="dropdown">
                <button type="button" class="btn btn-primary dropbtn">
                <span class="glyphicon glyphicon-briefcase"></span>
                Accounts
                <span class="caret"></span></button>
                <div class="dropdown-content">
                    <a href="#">Sub Menu 1</a>
                    <a href="#">Sub Menu 2</a>
                    <a href="#">Sub Menu 3</a>
                    <a href="#">Sub Menu 4</a>
                    <a href="#">Sub Menu 5</a>
                </div>
            </li>
            <li class="dropdown">
                <button type="button" class="btn btn-primary dropbtn">
                <span class="glyphicon glyphicon-headphones"></span>
                Service Desk
                <span class="caret"></span></button>
                <div class="dropdown-content">
                    <a href="#">Sub Menu 1</a>
                    <a href="#">Sub Menu 2</a>
                    <a href="#">Sub Menu 3</a>
                    <a href="#">Sub Menu 4</a>
                </div>
            </li>
            <li class="dropdown">
                <button type="button" class="btn btn-primary dropbtn">
                <span class="glyphicon glyphicon-file"></span>
                Reports
                <span class="caret"></span></button>
                <div class="dropdown-content">
                    <a href="#">Sub Menu 1</a>
                    <a href="#">Sub Menu 2</a>
                    <a href="#">Sub Menu 3</a>
                    <a href="#">Sub Menu 4</a>
                    <a href="#">Sub Menu 5</a>
                </div>
            </li>
            <li class="dropdown">
                <button type="button" class="btn btn-primary dropbtn">
                <span class="glyphicon glyphicon-cog"></span>
                Settings
                <span class="caret"></span></button>
                <div class="dropdown-content">
                    <a href="#">Sub Menu 1</a>
                    <a href="#">Sub Menu 2</a>
                    <a href="#">Sub Menu 3</a>
                </div>
            </li>
        </ul>
    </div>
</nav>

And the CSS

.dropdown {
    float: left;
    padding-right: 1px;
}

.dropbtn{
    border: 0px;
    height: 30px;
    border-radius: 0px 10px;
}
li button, .dropbtn {
    display: inline-block;
    color: white;
    text-align: center;
}

li button:hover, .dropdown:hover .dropbtn {
    background-color: #12A5F4;
}

.dropbtn.active {
    background: #12A5F4;
}

.dropdown-content {
    display: none;
    position: absolute;
    background-color: #e8f3f4;
    min-width: 100%;
    box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.1);
    z-index: 10;
}

.navbar-header{
    overflow: visible;
    z-index: 1;
}

.dropdown-content a {
    color: black;
    padding: 5px 10px;
    display: block;
    text-align: left;
}

.dropdown-content a:hover {
    background-color: #d8dee2
}

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

#menubar{
    padding-top: 5px;
    overflow: visible;
    z-index: 10;
    padding-left: 0px;
    padding-right: 0px;
    margin: 0px;
}

#dropdownNavbar{
    margin: 0px;
}

.navbar-toggle{
    background-color: #3382d5;
}
.navbar-toggle span{
    background-color: white;
}
Geri answered 24/2, 2017 at 11:58 Comment(0)
H
1

<!DOCTYPE html>
<html>
<head>
<style>
.dropbtn {
    background-color: #4CAF50;
    color: white;
    padding: 16px;
    font-size: 16px;
    border: none;
    cursor: pointer;
}

.dropdown {
    position: relative;
    display: inline-block;
}

.dropdown-content {
    display: none;
    position: absolute;
    background-color: #f9f9f9;
    min-width: 160px;
    box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
    z-index: 1;
}

.dropdown-content a {
    color: black;
    padding: 12px 16px;
    text-decoration: none;
    display: block;
}

.dropdown-content a:hover {background-color: #f1f1f1}

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

.dropdown:hover .dropbtn {
    background-color: #3e8e41;
}
</style>
</head>
<body>

<h2>Hoverable Dropdown</h2>
<p>Move the mouse over the button to open the dropdown menu.</p>

<div class="dropdown">
  <button class="dropbtn">Dropdown</button>
  <div class="dropdown-content">
    <a href="#">Link 1</a>
    <a href="#">Link 2</a>
    <a href="#">Link 3</a>
  </div>
</div>

</body>
</html>
Harmonics answered 19/7, 2017 at 7:17 Comment(0)
D
1

Adding this for those who want default functionality on mobile devices. Can set min-width: ... as required

@media only screen and (min-width: 1195px) {
  ul.nav li.dropdown:hover > ul.dropdown-menu {
    display: block;
  }
  ul.nav li.dropdown> ul.dropdown-menu {
    display: none;
  }
}

setting display: none so that dropdown-toggle won't create an issue. If you leave it as is, there might be two dropdowns open at the same time.

Divulsion answered 23/2, 2018 at 0:47 Comment(0)
H
0
 <ul class="nav navbar-nav">
        <li class="active"><a href="#">Link</a></li>
        <li><a href="#">Link</a></li>
        <li class="dropdown">
          <a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown <b class="caret"></b></a>
          <ul class="dropdown-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><a href="#">Separated link</a></li>
            <li class="divider"></li>
            <li><a href="#">One more separated link</a></li>
          </ul>
        </li>
      </ul>
      <script>
        $('ul.nav li.dropdown').hover(function() {
        $(this).find('.dropdown-menu').stop(true, 
        true).delay(200).fadeIn(500);
        }, function() {
        $(this).find('.dropdown-menu').stop(true, 
        true).delay(200).fadeOut(500);
        });
      </script>
Hoptoad answered 6/7, 2017 at 10:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.