Drop Down Menu Design
When Twitter Bootstrap 3 was released one element that was missing was support for multi-level dropdown menus. While the Bootstrap developers argued that the need for multi-level was minimal at best, the fact remained that removing them from the core product left many web developers out in the cold. While there is many articles providing workarounds through CSS to achieve desired results, one critical piece that is missing from the puzzle is responsive support. While the workarounds work great for desktops, laptops, and even some tablets, they fail to work for all mobile devices.
After endless Google searches and hacking around in the Bootstrap 3.0 JavaScript file I was able to create a workaround that works that is responsive and works on all devices.
Since I needed this solution for a WordPress site, I am going to provide instructions here for incorporating with the Bootstrap Nav Walker class by Edward McIntyre (https://github.com/twittem/wp-bootstrap-navwalker).
Multi Level Drop Down Menu
STEP 1
Add the following to your CSS file:
.dropdown-submenu{position:relative;}
.dropdown-submenu > .dropdown-menu{top:0;left:100%;-webkit-border-radius:0 6px 6px 6px;-moz-border-radius:0 6px 6px 6px;border-radius:0 6px 6px 6px;}
.dropdown-submenu:active > .dropdown-menu{display:block;}
.dropdown-submenu > a:after{display:block;content:" ";float:right;width:0;height:0;border-color:transparent;border-style:solid;border-width:5px 0 5px 5px;border-left-color:#cccccc;margin-top:5px;margin-right:-10px;}
.dropdown-submenu:active > a:after{border-left-color:#ffffff;}
.dropdown-submenu.pull-left{float:none;}.dropdown-submenu.pull-left > .dropdown-menu{left:-100%;margin-left:10px;-webkit-border-radius:6px 0 6px 6px;-moz-border-radius:6px 0 6px 6px;border-radius:6px 0 6px 6px;}
It is important to note in the above CSS, that many of the solutions out there set the .dropdown-menu state to hover. While this works great on the desktop, unfortunately hover events do not work as wonderfully on mobile devices. We therefore have set the state to active in this solution.
Step 2
In the bootstrap.js file we are going to make a minor hack to the clearMenus function (approximately line 772).
function clearMenus() {
$(backdrop).remove()
$(toggle).each(function (e) {
var $parent = getParent($(this))
if (!$parent.hasClass('open')) return
$parent.trigger(e = $.Event('hide.bs.dropdown'))
if (e.isDefaultPrevented()) return
// Remove the following line of code for support of multi-level menus
//$parent.removeClass('open').trigger('hidden.bs.dropdown')
})
}
function clearAllMenus() {
$(backdrop).remove()
$(toggle).each(function (e) {
var $parent = getParent($(this))
if (!$parent.hasClass('open')) return
$parent.trigger(e = $.Event('hide.bs.dropdown'))
if (e.isDefaultPrevented()) return
$parent.removeClass('open').trigger('hidden.bs.dropdown')
})
}
You will note that we commented out the last line of the function. The open class is what keeps that dropdown menu visible when selecting an item. The problem with a multi-level menu is that the open class is getting removed when you proceed to another level thus making the entire menu disappear. We needed to keep the menu open while the levels are navigated.
Step 3
There was an issue with menus not closing if no option was selected. So we need to add change the following lines of code to resolve that issue (approximately lines 838-843:
$(document)
.on('click.bs.dropdown.data-api', clearMenus)
.on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
.on('click.bs.dropdown.data-api' , toggle, Dropdown.prototype.toggle)
.on('keydown.bs.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown)
.on('click', clearAllMenus)
Step 4
In the wp_bootstrap_navwalker class we are going to make an edit at around line 80.
First we are going to remove (or comment out) the following:
if ( $args->has_children )
$class_names .= ' dropdown';
Step 5
The final step is going to be to adjust the menu when we create it in our header.php file (or wherever you initialise your menu bar):
wp_nav_menu( array(
'menu' => 'primary',
'theme_location' => 'primary',
'depth' => 3,
'container' => '',
'container_class' => '',
'menu_class' => 'nav navbar-nav no-float',
'fallback_cb' => 'wp_bootstrap_navwalker::fallback',
'walker' => new wp_bootstrap_navwalker())
);
You will note that we changed the depth to whatever depth we want, in this case 3. This allows us to have 3 levels of menus.
And there you have it, a multi level drop down using Bootstrap 3, any issues or difficulties implementing this just drop a comment below!