Bootstrap 3: navbar dropdown opening on hover and opening on click for collapsed navbar

The Bootstrap 3 css framework contains a pretty good navigation component called “navbar”. The navbar automatically collapse when the viewport is too small. The menu’s of the navbar open when clicking the main item. For a tablet or phone this behavior is fine, but when using a desktop you might want the menu’s to open when hovering them. It took me some time to figure out a solution to enable this behavior which kept the click behavior for tablets and phones.

2014-10-23: There’s an updated version at: Boostrap navbar opens on hover with clickable parent which supports effects/animations and the parent remains navigable.

The Bootstrap 3 css framework contains a pretty good navigation component called “navbar”. The navbar automatically collapse when the viewport is too small. The menu’s of the navbar open when clicking the main item. For a tablet or phone this behavior is fine, but when using a desktop you might want the menu’s to open when hovering them. It took me some time to figure out a solution to enable this behavior which kept the click behavior for tablets and phones.

Create the navbar

Let’s start with creating a navbar in HTML:

<nav class="navbar navbar-default" role="navigation">
    <div class="container">
        <div class="navbar-header">
            <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#main-menu">
                <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 hidden-md hidden-lg" href="#">Menu</a>
        </div>

        <div class="collapse navbar-collapse" id="main-menu">
            <ul class="nav navbar-nav">
                <li class="active"><a href="#">Home</a></li>
                <li class="dropdown">
                    <a href="#" class="dropdown-toggle" data-toggle="dropdown">About <span class="caret"></span></a>
                    <ul class="dropdown-menu">
                        <li><a href="#">History</a></li>
                        <li><a href="#">Organisation</a></li>
                        <li><a href="#">Membership</a></li>
                    </ul>
                </li>
                <li><a href="#">News</a></li>
                <li class="dropdown">
                    <a href="#" class="dropdown-toggle" data-toggle="dropdown">Portfolio <span class="caret"></span></a>
                    <ul class="dropdown-menu">
                        <li><a href="#">ICT consultancy</a></li>
                        <li><a href="#">Support on location</a></li>
                        <li><a href="#">Webdevelopment</a></li>
                    </ul>
                </li>
                <li><a href="#">Contact</a></li>
            </ul>
        </div> 
    </div>
</nav>

The navbar looks like:

navbar

The menu items which contain a submenu are marked by the caret. Clicking on those menu items will show the submenu. Let’s change its behavior to open on a hover event.

Submenu opening when hovering

First we need to figure out if the navbar is collapsed or not. The easiest way to do is to determine the window width. With a width lower then 768 pixel, it will collapse. So when the width is 768 or higher, we want the submenu to show when hovering, a effect which is usually trigger by a click. Let’s take this knowledge to a javascript function:

function toggleNavbarMethod() {
    if ($(window).width() > 768) {
        $('.navbar .dropdown').on('mouseover', function(){
            $('.dropdown-toggle', this).trigger('click'); 
        });
    }
}

The submenu is now showing when hovering the parent menu item. Hovering out doesn’t close the submenu, a feature we want. That means we need to add some functionality to the hover out event:

function toggleNavbarMethod() {
    if ($(window).width() > 768) {
        $('.navbar .dropdown').on('mouseover', function(){
            $('.dropdown-toggle', this).trigger('click'); 
        }).on('mouseout', function(){
            $('.dropdown-toggle', this).trigger('click').blur();
        });
    }
}

This will trigger a click event once more when hover out. As a second click closes the submenu, we simulate this behavior. Also we want to get rid of the focus on the parent menu item. Therefor I added the blur();. But when the width is lower then 768 pixels, we need to fall back to the original “click to open” method. So lets remove the mouseover and mouseout event listeners:

function toggleNavbarMethod() {
    if ($(window).width() > 768) {
        $('.navbar .dropdown').on('mouseover', function(){
            $('.dropdown-toggle', this).trigger('click'); 
        }).on('mouseout', function(){
            $('.dropdown-toggle', this).trigger('click').blur();
        });
    }
    else {
        $('.navbar .dropdown').off('mouseover').off('mouseout');
    }
}

The navbar is fully functional and opens the submenu’s when hovering it’s parent as long as the navbar isn’t collapsed.

Determining submenu behavior when resizing the window

But what if the user resizes his window? The navbar submenu behavior needs to be determined again. We can do that by adding a resize event listener:

$(window).resize(toggleNavbarMethod);

The last thing we need to do, is to activate the script and bind the resize listener.

Final script

$(document).ready(function() {
    function toggleNavbarMethod() {
        if ($(window).width() > 768) {
            $('.navbar .dropdown').on('mouseover', function(){
                $('.dropdown-toggle', this).trigger('click'); 
            }).on('mouseout', function(){
                $('.dropdown-toggle', this).trigger('click').blur();
            });
        }
        else {
            $('.navbar .dropdown').off('mouseover').off('mouseout');
        }
    }
    toggleNavbarMethod();
    $(window).resize(toggleNavbarMethod);
});

Demo

A demo can be found on Bootply. If you have any problems or question, drop your question below or contact me at twitter.

To open the dropdown menu on hover but the parent remains clickable, I made a Bootply snippet: http://www.bootply.com/5e07KUQ90v

Create the navbar

Let’s start with creating a navbar in HTML:

<nav class="navbar navbar-default" role="navigation">
    <div class="container">
        <div class="navbar-header">
            <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#main-menu">
                <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 hidden-md hidden-lg" href="#">Menu</a>
        </div>

        <div class="collapse navbar-collapse" id="main-menu">
            <ul class="nav navbar-nav">
                <li class="active"><a href="#">Home</a></li>
                <li class="dropdown">
                    <a href="#" class="dropdown-toggle" data-toggle="dropdown">About <span class="caret"></span></a>
                    <ul class="dropdown-menu">
                        <li><a href="#">History</a></li>
                        <li><a href="#">Organisation</a></li>
                        <li><a href="#">Membership</a></li>
                    </ul>
                </li>
                <li><a href="#">News</a></li>
                <li class="dropdown">
                    <a href="#" class="dropdown-toggle" data-toggle="dropdown">Portfolio <span class="caret"></span></a>
                    <ul class="dropdown-menu">
                        <li><a href="#">ICT consultancy</a></li>
                        <li><a href="#">Support on location</a></li>
                        <li><a href="#">Webdevelopment</a></li>
                    </ul>
                </li>
                <li><a href="#">Contact</a></li>
            </ul>
        </div> 
    </div>
</nav>

The navbar looks like:

navbar

The menu items which contain a submenu are marked by the caret. Clicking on those menu items will show the submenu. Let’s change its behavior to open on a hover event.

Submenu opening when hovering

First we need to figure out if the navbar is collapsed or not. The easiest way to do is to determine the window width. With a width lower then 768 pixel, it will collapse. So when the width is 768 or higher, we want the submenu to show when hovering, a effect which is usually trigger by a click. Let’s take this knowledge to a javascript function:

function toggleNavbarMethod() {
    if ($(window).width() > 768) {
        $('.navbar .dropdown').on('mouseover', function(){
            $('.dropdown-toggle', this).trigger('click'); 
        });
    }
}

The submenu is now showing when hovering the parent menu item. Hovering out doesn’t close the submenu, a feature we want. That means we need to add some functionality to the hover out event:

function toggleNavbarMethod() {
    if ($(window).width() > 768) {
        $('.navbar .dropdown').on('mouseover', function(){
            $('.dropdown-toggle', this).trigger('click'); 
        }).on('mouseout', function(){
            $('.dropdown-toggle', this).trigger('click').blur();
        });
    }
}

This will trigger a click event once more when hover out. As a second click closes the submenu, we simulate this behavior. Also we want to get rid of the focus on the parent menu item. Therefor I added the blur();. But when the width is lower then 768 pixels, we need to fall back to the original “click to open” method. So lets remove the mouseover and mouseout event listeners:

function toggleNavbarMethod() {
    if ($(window).width() > 768) {
        $('.navbar .dropdown').on('mouseover', function(){
            $('.dropdown-toggle', this).trigger('click'); 
        }).on('mouseout', function(){
            $('.dropdown-toggle', this).trigger('click').blur();
        });
    }
    else {
        $('.navbar .dropdown').off('mouseover').off('mouseout');
    }
}

The navbar is fully functional and opens the submenu’s when hovering it’s parent as long as the navbar isn’t collapsed.

Determining submenu behavior when resizing the window

But what if the user resizes his window? The navbar submenu behavior needs to be determined again. We can do that by adding a resize event listener:

$(window).resize(toggleNavbarMethod);

The last thing we need to do, is to activate the script and bind the resize listener.

Final script

$(document).ready(function() {
    function toggleNavbarMethod() {
        if ($(window).width() > 768) {
            $('.navbar .dropdown').on('mouseover', function(){
                $('.dropdown-toggle', this).trigger('click'); 
            }).on('mouseout', function(){
                $('.dropdown-toggle', this).trigger('click').blur();
            });
        }
        else {
            $('.navbar .dropdown').off('mouseover').off('mouseout');
        }
    }
    toggleNavbarMethod();
    $(window).resize(toggleNavbarMethod);
});

Demo

A demo can be found on Bootply. If you have any problems or question, drop your question below or contact me at twitter.

20 Replies to “Bootstrap 3: navbar dropdown opening on hover and opening on click for collapsed navbar”

    1. That’s true, but it has some side effects. The collapsed navbar wil now open the dropdowns on hovering also, which you probably don’t want. The javascript above, simulates a hover as a click and once the navbar collaps, it disables itself.

      1. Thanks for your great script. Its good but not perfect as its working fine but if on pc you reduce the size of window to get collapsed navbar its opening on click which is right but then after maximizing window its still on click & no changing on hover so you need to refresh the script somehow for this change in window size i think.

        Sorry i am not a developer & don’t know much about scripts but i am just posting what i found.. Thanks 4 all your efforts 🙂

  1. Thank you for this, it helped me a lot.
    In my case, I have multiple nav bars and the trigger point for collapse is set to different widths in custom media queries. Giving the button an id (say “hs_button”) and changing the test to
    if ($(‘#hs_button’).css(‘display’) == ‘none’) {
    allows your code to respond to what bootstrap is actually doing, rather than assuming the default trigger width.

    1. Thank you for the feedback. I’m going to test your solution. You can also use .is(‘:hidden’) instead of .css(“display”) == “none”.

  2. This works nice, but when you have input filed in dropdown, does not work, tried

    $(‘.dropdown-menu input, .dropdown-menu label’).click(function (e) {
    e.stopPropagation();
    });

    But still no luck? Any fix for this?

  3. This is great, but I had to use ‘mouseenter/mouseleave’ instead of ‘mouseover/mouseout’ as I was also animating the menus, and of course mouseover fires constantly as you move your mouse over the trigger area.

  4. There is a bug in this demo/bootply… when you mouseout/hover from a dropdown to a non drowdown link on the menu the previous drop down opens (eg from portfolio to contact). If hovering from dropdown to dropdown all is ok.

  5. Oops… forgot to add this happens after you click on a dropdown (which msome people might still do).

    Hover over drop down (it auto opens)
    Click on the open dropdown (manually closes it)
    Hover to next menu link (previous open dropdown auto opens again)

    1. I have found a issue i can’t figure out how to solve it.
      in http://www.bootply.com/5e07KUQ90v , change to mobile mode, than go to last drop down menu and near Separated link you have 2 lines. Move over one of those lines and click once the hand pointer is gone. Once you do it, the menu closes. It must stay expanded until you make a click on the Drop down menu or any link inside it, and it must stay open on any click inside the drop down (except actual links).

      To give a example. Inside such drop down menu, i will add some tabs which have content and when i click on a tab the menu collapses or when i click in a empty area inside that menu.

  6. This is the best demo having the navbar menu behave on rollover only when it’s viewed from desktop screen.

  7. for 2nd level menu not working for me in mobile…its open when hover on 1st menu…please help me

  8. You can do it without any scripting language. Just try this.

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

Leave a Reply

Your email address will not be published. Required fields are marked *