Overview
I finally was able to begin using Twitter Bootstrap in a recent project for which I am recreating a complex navigation into the new Bootstrap interface. But, I found that while I needed to support nested nav lists within the top level nav list, Bootstrap doesn't seem to have any built in support for it: Bootstrap Navbar.So, I built support for it; and here's what I came up with:
(screenshot)

The Code
I wanted to preserve Bootstrap's naming convention and HTML structure, so I didn't want to do anything really very new. I also wanted to retain their common styling, but come up with something that worked for sub navigation. So, I started with adding my HTML(forgive the html styling here, the tool I'm using doesn't prettify very well):
Next, I needed to start styling; using their common style, I enhanced the nexted nav functionality by adding :hover state show/hide of the sub menu list.
.nav li.dropdown ul.dropdown-menu li:hover ul {
display:block;
position:absolute;
left:100%;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
}
.nav li.dropdown ul.dropdown-menu ul {
display: none;
float:right;
position: relative;
top: auto;
margin-top: -27px;
}
Bootstrap on it's own adds carets (the arrows) for dropdown menus, and sort of assumes the sub-nav will always be below your menu item. So the menu item's caret/arrow always pointed down, and the sub-nav's menu arrow always pointed up; I needed to address this:.nav li.dropdown ul.dropdown-menu .nav-list .caret {
border-bottom-color: #999;
border-top-color: #999;
float: right;
}
.nav li.dropdown ul.dropdown-menu .nav-list:hover .caret {
margin-left: 6px;
margin-top: 5px;
margin-right: 1px;
border-right: 0;
border-left: 4px solid #fff;
border-top: 4px solid transparent;
border-bottom: 4px solid transparent;
}
.nav li.dropdown ul .nav-list .dropdown-menu:after {
top: 8px;
left: -12px;
border-top: 6px solid transparent;
border-bottom: 6px solid transparent;
border-right: 6px solid #fff;
}
.nav li.dropdown ul .nav-list .dropdown-menu:before {
left: -7px;
border-left: 0;
top: 7px;
border-top: 7px solid transparent;
border-bottom: 7px solid transparent;
border-right: 7px solid rgba(0,0,0,0.05);
}
Here things began to get a little tricky; specifically, Bootstrap uses CSS borders to draw their carets/arrows (which I think is a great approach by the way); this is fine, but because I'm inheriting their styles on my new nav element, I needed to reverse the borders I didn't want so I could adjust the direction of my caret/arrow to the right and left (for the sub nav); then I could add the styles I did need, with colors appropriate for my nesting.Finally, I added in some common list item over styling:
.nav li.dropdown ul.dropdown-menu li.nav-list:hover {
background: #08c;
color: #fff;
cursor: pointer;
}
.nav li.dropdown ul.dropdown-menu .nav-list {
font-size: 13px;
color: #333;
float: none;
line-height: 21px;
}
Note that I only bothered to go one level deep on the sub menu, though it would be easy enough to make that work if you needed it to.
ReplyDeletelove the result, and was able to get it working with your example using your css. Though when I just dropped it into my custom css after first including bootstrap.min.css, its mostly non-functional, doubling the height of my navbar, floating half way down, and all menu items visible with no sub-menu functionality. Will have to track down the css conflicts I guess, mostly learning this stuff as I go, so I'm sure its just me.
ReplyDeleteI'd be happy to help troubleshoot if you like. It sounds like there is some positioning and/or overflow issues. Shoot me an email and we'll work through it.
ReplyDeleteafter some help from Scott, ended up being an editor specific issue. Sub-menus are looking great! Awesome article.
ReplyDeleteMaybe I helped push them over the edge: http://blog.getbootstrap.com/2012/08/20/bootstrap-2-1-0-released/
ReplyDelete"Submenu support on dropdowns. We avoided this for some time as we thought it would unnecessarily complicate things, but we've backtracked on that and opted to add them in. See the docs for more info."
There is an issue on this kind of horizontal sub-menu.
ReplyDeleteWe have to move the mouse strictly straight into the sub-menu, otherwise the unintentional mouse out will make the sub-menu disappear.
I think a little bit javascript timeout would be more fit for the inconsistent mouse-menu direction sub-menu.
Thanks for you comment, and I totally agree. However, the approach here was to utilize only html and css to achieve what bootstrap (in their earlier version) did not support. An interesting, non-js approach could be to play with css animation / timing on those mouseovers; for example, on blur, wait .5s before hiding your submenu. Or something to that effect. :)
ReplyDelete