Scrollable Twitter Bootstrap Menus

Twitter Bootstrap has some pretty nice features, but one of the more common practices left out of its component stack is the ability to have long dropdown menus that scroll their content. A quick search on Google brought up some possible solutions, but a lot of them involved JavaScript/Plug-ins or directly hacked into the CSS of bootstrap. Each of which have their own advantages (JavaScript allows for more control, CSS only prevents unnecessary DOM manipulations). However, I’ve typically find myself consumed in the abyss of hacks that worked, but just so happened to brake another functionality of the framework I’m using. Sure, the hack may work in a lot of situations… but just not mine šŸ˜¦ So, instead of taking another performance hit with a JS solution or using just CSS that may have some unintended consequences, I decided to use a combination of CSS and HTML to tackle the problem. The use of a few extra HTML tags along with some *hopefully* less intrusive CSS will lessen the chances that I’d screw up the intended purpose of the component I’m trying to add the feature to!

Here are a few benefits that this approach will give us:

  • No JavaScript
  • Does not interfere with the layout/CSS of the menu you’re trying to scroll content for
  • Works with multiple scroll-menu in the same dropdown-menu
  • Works with dropdown-submenu
  • Works in responsive mode and mobile/touch enabled
  • Allows for static headers and footers that will not scroll with the content using the normal list items
  • The scroll-menu will grow dynamically until it reaches the max-height (at which point it will show a vertical scrollbar for each scroll-menu)

Well, I’ll cut to the chase and give you the solution I came up with *because nothings more irritating than trying to search through all the wrong ways someone did something before you find the final solution* (or you can jump to the finalĀ JFiddle example)

CSS

/* So we wont impact the original bootstrap menu
or it's pseudo call-out arrow the menu is wrapped
in a sub dropdown-menu with a chained scroll-menu */
ul.scroll-menu {
    position: relative;
    display: inherit !important;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    -moz-overflow-scrolling: touch;
    -ms-overflow-scrolling: touch;
    -o-overflow-scrolling: touch;
    overflow-scrolling: touch;
    top: 0 !important;
    left: 0 !important;
    width: 100%;
    height: auto;
    max-height: 500px;
    margin: 0;
    border-left: none;
    border-right: none;
    -webkit-border-radius: 0 !important;
    -moz-border-radius: 0 !important;
    -ms-border-radius: 0 !important;
    -o-border-radius: 0 !important;
    border-radius: 0 !important;
    -webkit-box-shadow: none;
    -moz-box-shadow: none;
    -ms-box-shadow: none;
    -o-box-shadow: none;
    box-shadow: none;
}

HTML

<!-- Example of a single scrollable dropdown-menu navigation 	 (notice the placement of the "scroll-menu" class) --></pre>
<ul class="nav">
	<li class="dropdown"><a href="#" data-toggle="dropdown">
 <b class="icon-th-large icon-white"></b>
 </a>
<ul class="dropdown-menu">
<ul class="dropdown-menu"><!-- static non-scrollable menu header --></ul>
</ul>
<ul class="dropdown-menu">
<ul class="dropdown-menu">
	<li class="disabled"><a href="#"><b>My Theme:</b></a></li>
	<li><!-- Here we have our dropdown-menu wrapper so we don't mess 					 with the layout of the outer dropdown-menu -->
<ul class="dropdown-menu scroll-menu">
<ul class="dropdown-menu scroll-menu">
	<li><a href="#"><i class="icon-asterisk"></i> Start</a></li>
	<li><a href="#"><i class="icon-minus"></i> UI Lightness</a></li>
</ul>
</ul>
<ul class="dropdown-menu scroll-menu"><!-- Keep adding more list items and watch how your menu 						 will grow w/o a vertical scollbar until it reaches 						 the max-height set in the scroll-menu class --></ul>
</li>
</ul>
</ul>
<ul class="dropdown-menu">
<ul class="dropdown-menu"><!-- static non-scrollable menu footer --></ul>
</ul>
<ul class="dropdown-menu">
	<li class="disabled"><a href="#">
 <i class="icon-chevron-up pull-left"></i>
 <i class="icon-chevron-up pull-right"></i>
 </a></li>
</ul>
</li>
</ul>
<pre>

Result

scroll-menu1

Now that we have a scroll-menu working that’s decoupled from our main dropdown-menu, lets try to add multiple scroll-menus to our main dropdown-menu (again, you can skip to the complete JFiddle example if you’d like):

HTML

<!-- Example of a multiple scrollable dropdown-menu navigation      (notice the placement of the "scroll-menu" class as well      as the "scroll-menu-2x" class that helps to cut the      max-height down to about 1/2 the size of our normal      scroll-menu max-height) --></pre>
<ul class="nav">
	<li class="dropdown"><a href="#" data-toggle="dropdown">
 <b class="icon-key icon-white"></b>
 </a>
<ul class="dropdown-menu">
<ul class="dropdown-menu"><!-- static non-scrollable menu header 1 --></ul>
</ul>
<ul class="dropdown-menu">
<ul class="dropdown-menu">
	<li class="disabled"><a href="#"><i class="icon-group"></i> <b>My Groups</b></a></li>
	<li>
<ul class="dropdown-menu scroll-menu scroll-menu-2x">
<ul class="dropdown-menu scroll-menu scroll-menu-2x">
	<li><a href="#">User</a></li>
	<li><a href="#">Administrators</a></li>
	<li><a href="#">Some Other Group</a></li>
</ul>
</ul>
<ul class="dropdown-menu scroll-menu scroll-menu-2x"><!-- Additional menu items omitted for brevity --></ul>
</li>
</ul>
</ul>
<ul class="dropdown-menu">
<ul class="dropdown-menu"><!-- static non-scrollable menu header 2 --></ul>
</ul>
<ul class="dropdown-menu">
<ul class="dropdown-menu">
	<li class="disabled"><a href="#"><i class="icon-user"></i> <b>My Roles</b></a></li>
	<li>
<ul class="dropdown-menu scroll-menu scroll-menu-2x">
<ul class="dropdown-menu scroll-menu scroll-menu-2x">
	<li><a href="#">Core Users</a></li>
	<li><a href="#">Admin</a></li>
	<li><a href="#">Some Other Role</a></li>
</ul>
</ul>
<ul class="dropdown-menu scroll-menu scroll-menu-2x"><!-- Additional menu items omitted for brevity --></ul>
</li>
</ul>
</ul>
<ul class="dropdown-menu">
<ul class="dropdown-menu"><!-- static non-scrollable menu footer --></ul>
</ul>
<ul class="dropdown-menu">
	<li class="disabled"><a href="#">
 <i class="icon-chevron-up pull-left"></i>
 <i class="icon-chevron-up pull-right"></i>
 </a></li>
</ul>
</li>
</ul>
<pre>

Result

scroll-menu2

…and last, but not least we have the famed dropdown-submenu. This is where a lot of other solutions either partially work or do not work at all. While the proposed hack I’m suggesting may not be perfect it seems to get us going with a minimal impact on the core bootstrap implementation. Most of the HTML below should look almost identical to the way the normal dropdown-menu / dropdown-submenu is laid out with the addition of an added “dropdown-menu scroll-menu“:

scroll-menu3

Let me know if you find a better solution or have made improvements to the original JFiddle example!

Advertisements