Bootstrap Navbar without jQuery

While I’m fond of Bootstrap in general, I dislike how much it relies on JavaScript and particularly dislike its dependency on jQuery. I have nothing against using JavaScript for creating interactive content, e.g. web applications, or progressive enhancement, e.g. lightboxes or copying text to the clipboard, but I do take issue with requiring JavaScript for basic site functionality as is the case with Bootstrap’s navbar and dropdowns. What I particularly dislike is that not only does this require JavaScript, but it requires a 32kB JavaScript library, jQuery, to do what would otherwise take less than 1kB of JavaScript. To avoid this when redesigning campworkcoeman.org, I made some modifications to open the navbar’s dropdowns on hover on larger devices and used a small piece of plain JavaScript to operate the menu on small, mobile devices. Unfortunately, this didn’t work properly under iOS, but I recently fixed this. I’m detailing the changes I made in case someone finds them useful.

As far as HTML goes, the only change is using <div> elements instead of <a> elements for the dropdown-toggle class. In the CSS, a media query is used to open the dropdowns on hover on larger devices, and some code is added to restore the appearance of the dropdowns due to the HTML change.

/*
 * Open dropdowns on hover instead of click.
 */
@media (min-width: 768px) {
  .dropdown:hover {
    background: #e7e7e7;
  }
  .dropdown:hover > .dropdown-menu {
    display: block;
  }
}

/*
 * The following is needed since the dropdowns are <div>
 * elements instead of <a> elements
 */
.nav > li > div {
  position: relative;
  display: block;
  padding: 10px 15px;
  cursor: default;
}
.navbar-nav > li > div {
  padding-top: 15px;
  padding-bottom: 15px;
  line-height: 20px;
}
.navbar-default .navbar-nav > li > div {
  color: rgb(119, 119, 119);
}
.navbar-collapse.collapse {
  display: none;
}
.dropdown-open {
  background: #e7e7e7;
}

Finally, a small script replaces the default Bootstrap bootstrap.js version.

// Navbar and dropdowns
var toggle = document.getElementsByClassName('navbar-toggle')[0],
    collapse = document.getElementsByClassName('navbar-collapse')[0],
    dropdowns = document.getElementsByClassName('dropdown');;

// Toggle if navbar menu is open or closed
function toggleMenu() {
    collapse.classList.toggle('collapse');
    collapse.classList.toggle('in');
}

// Close all dropdown menus
function closeMenus() {
    for (var j = 0; j < dropdowns.length; j++) {
        dropdowns[j].getElementsByClassName('dropdown-toggle')[0].classList.remove('dropdown-open');
        dropdowns[j].classList.remove('open');
    }
}

// Add click handling to dropdowns
for (var i = 0; i < dropdowns.length; i++) {
    dropdowns[i].addEventListener('click', function() {
        if (document.body.clientWidth < 768) {
            var open = this.classList.contains('open');
            closeMenus();
            if (!open) {
                this.getElementsByClassName('dropdown-toggle')[0].classList.toggle('dropdown-open');
                this.classList.toggle('open');
            }
        }
    });
}

// Close dropdowns when screen becomes big enough to switch to open by hover
function closeMenusOnResize() {
    if (document.body.clientWidth >= 768) {
        closeMenus();
        collapse.classList.add('collapse');
        collapse.classList.remove('in');
    }
}

// Event listeners
window.addEventListener('resize', closeMenusOnResize, false);
toggle.addEventListener('click', toggleMenu, false);

I modified Bootstrap’s navbar example to demonstrate this.

This entry was posted in and tagged , , , . Bookmark the permalink.

8 Responses to Bootstrap Navbar without jQuery

    Leave a Reply

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