Megamenu

Megamenu

HTML Source Code

<div role="menubar">
  <!-- role="group" -->
  <ul id="mega-menu" role="presentation" >
    <li id="home"  role="presentation"><a href="#" role="menuitem" aria-setsize="5" aria-posinset="1"><i class="fa fa-home"></i>Home</a></li>
    <li id="about" class="has-drop"  role="presentation"><a href="#" role="menuitem" aria-haspopup="true" aria-setsize="5" aria-posinset="2"><i class="fa fa-users"></i>About<i class="fa fa-toggle-down fa-1"></i></a>
      <div class="droplet">
        <div role="group" aria-labelledby="about-head-a1" class="col">
          <h2 id="about-head-a1" class="col-head">Heading</h2>
          <ul>
            <li role="presentation"><a href="#" role="menuitem" aria-setsize="4" aria-posinset="1">Item 1</a></li>
            <li role="presentation"><a href="#" role="menuitem" aria-setsize="4" aria-posinset="2">Item 2</a></li>
            <li role="presentation"><a href="#" role="menuitem" aria-setsize="4" aria-posinset="3">Item 3</a></li>
            <li role="presentation"><a href="#" role="menuitem" aria-setsize="4" aria-posinset="4">Item 4</a></li>
          </ul>
        </div>
        <div role="group" aria-labelledby="about-head-a2" class="col">
          <h2 id="about-head-a2" class="col-head">Heading</h2>
          <ul>
            <li role="presentation"><a href="#" role="menuitem" aria-setsize="4" aria-posinset="1">Item 5</a></li>
            <li role="presentation"><a href="#" role="menuitem" aria-setsize="4" aria-posinset="2">Item 6</a></li>
            <li role="presentation"><a href="#" role="menuitem" aria-setsize="4" aria-posinset="3">Item 7</a></li>
            <li role="presentation"><a href="#" role="menuitem" aria-setsize="4" aria-posinset="4">Item 8</a></li>
          </ul>
        </div>
        <div role="group" aria-labelledby="about-head-a3" class="col">
          <h2 id="about-head-a3" class="col-head">Heading</h2>
          <ul>
            <li role="presentation"><a href="#" role="menuitem" aria-setsize="4" aria-posinset="1">Item 9</a></li>
            <li role="presentation"><a href="#" role="menuitem" aria-setsize="4" aria-posinset="2">Item 10</a></li>
            <li role="presentation"><a href="#" role="menuitem" aria-setsize="4" aria-posinset="3">Item 11</a></li>
            <li role="presentation"><a href="#" role="menuitem" aria-setsize="4" aria-posinset="4">Item 12</a></li>
          </ul>
        </div>
      </div>
    </li>
    <li id="contact" class="has-drop"><a href="#" role="menuitem" aria-haspopup="true" aria-setsize="5" aria-posinset="3"><i class="fa fa-smile-o"></i>Contact<i class="fa fa-toggle-down fa-1"></i></a>
      <div class="droplet">
        <div role="group" aria-labelledby="about-head-b1" class="col">
          <h2 id="about-head-b1" class="col-head">Heading</h2>
          <ul>
            <li role="presentation"><a href="#" role="menuitem" aria-setsize="4" aria-posinset="1">Item 1</a></li>
            <li role="presentation"><a href="#" role="menuitem" aria-setsize="4" aria-posinset="2">Item 2</a></li>
            <li role="presentation"><a href="#" role="menuitem" aria-setsize="4" aria-posinset="3">Item 3</a></li>
            <li role="presentation"><a href="#" role="menuitem" aria-setsize="4" aria-posinset="4">Item 4</a></li>
          </ul>
        </div>
        <div role="group" aria-labelledby="about-head-b2" class="col">
          <h2 id="about-head-b2" class="col-head">Heading</h2>
          <ul>
            <li role="presentation"><a href="#" role="menuitem" aria-setsize="4" aria-posinset="1">Item 5</a></li>
            <li role="presentation"><a href="#" role="menuitem" aria-setsize="4" aria-posinset="2">Item 6</a></li>
            <li role="presentation"><a href="#" role="menuitem" aria-setsize="4" aria-posinset="3">Item 7</a></li>
            <li role="presentation"><a href="#" role="menuitem" aria-setsize="4" aria-posinset="4">Item 8</a></li>
          </ul>
        </div>
        <div role="group" aria-labelledby="about-head-b3" class="col">
          <h2 id="about-head-b3" class="col-head">Heading</h2>
          <ul>
            <li role="presentation"><a href="#" role="menuitem" aria-setsize="4" aria-posinset="1">Item 9</a></li>
            <li role="presentation"><a href="#" role="menuitem" aria-setsize="4" aria-posinset="2">Item 10</a></li>
            <li role="presentation"><a href="#" role="menuitem" aria-setsize="4" aria-posinset="3">Item 11</a></li>
            <li role="presentation"><a href="#" role="menuitem" aria-setsize="4" aria-posinset="4">Item 12</a></li>
          </ul>
        </div>
      </div>
    </li>
    <li id="faqs" class="has-drop"><a href="#" role="menuitem" aria-haspopup="true" aria-setsize="5" aria-posinset="4"><i class="fa fa-question-circle"></i>FAQs<i class="fa fa-toggle-down fa-1"></i></a>
      <div class="droplet">
        <div role="group" aria-labelledby="about-head-c1" class="col">
          <h2 id="about-head-c1" class="col-head">Heading</h2>
          <ul>
            <li role="presentation"><a href="#" role="menuitem" aria-setsize="4" aria-posinset="1">Item 1</a></li>
            <li role="presentation"><a href="#" role="menuitem" aria-setsize="4" aria-posinset="2">Item 2</a></li>
            <li role="presentation"><a href="#" role="menuitem" aria-setsize="4" aria-posinset="3">Item 3</a></li>
            <li role="presentation"><a href="#" role="menuitem" aria-setsize="4" aria-posinset="4">Item 4</a></li>
          </ul>
        </div>
        <div role="group" aria-labelledby="about-head-c2" class="col">
          <h2 id="about-head-c2" class="col-head">Heading</h2>
          <ul>
            <li role="presentation"><a href="#" role="menuitem" aria-setsize="4" aria-posinset="1">Item 5</a></li>
            <li role="presentation"><a href="#" role="menuitem" aria-setsize="4" aria-posinset="2">Item 6</a></li>
            <li role="presentation"><a href="#" role="menuitem" aria-setsize="4" aria-posinset="3">Item 7</a></li>
            <li role="presentation"><a href="#" role="menuitem" aria-setsize="4" aria-posinset="4">Item 8</a></li>
          </ul>
        </div>
        <div role="group" aria-labelledby="about-head-c3" class="col">
          <h2 id="about-head-c3" class="col-head">Heading</h2>
          <ul>
            <li role="presentation"><a href="#" role="menuitem" aria-setsize="4" aria-posinset="1">Item 9</a></li>
            <li role="presentation"><a href="#" role="menuitem" aria-setsize="4" aria-posinset="2">Item 10</a></li>
            <li role="presentation"><a href="#" role="menuitem" aria-setsize="4" aria-posinset="3">Item 11</a></li>
            <li role="presentation"><a href="#" role="menuitem" aria-setsize="4" aria-posinset="4">Item 12</a></li>
          </ul>
        </div>
      </div>
    </li>
    <li id="links"  role="presentation"><a href="#" role="menuitem" aria-setsize="5" aria-posinset="5"><i class="fa fa-external-link"></i>Links</a></li>
  </ul>
</div>

JavaScript Source Code

Dependencies:

  • JQuery
function initMegaMenu() {
  var megaMenu = document.getElementById('mega-menu');
  // keyboard stuff
  $(megaMenu).delegate('li a', 'keydown', keyboardHandler);

  // mouse stuff
  $(' > li.has-drop', megaMenu).each(function () {
    var dropdown = $('.droplet', $(this)[0]);

    $(this).hover(
      function () {
        $(this).addClass('active');
        $('.droplet', megaMenu).each(function (index, drop) {
          if (drop !== dropdown) {
            $(drop).hide();
          }
        });

        $(dropdown).slideDown(100);

      }, function () {
        $(this).removeClass('active');
        $(dropdown).slideUp(100);
      }
    );
  });
}


function keyboardHandler(keyVent) {
  var target = keyVent.target;
  var which = keyVent.which;

  if (which === 39) { // RIGHT
    if (isTopLevel(target)) {
      // top level item
      var nextTopItem = adjacentTopLevelItem(target, 'next');

      if (nextTopItem) {
        keyVent.preventDefault();
        nextTopItem.focus();
      }
    } else {
      // dropdown item
      var nextDropletItem = adjacentDropdownItem(target, 'next');
      if (nextDropletItem) {
        keyVent.preventDefault();
        nextDropletItem.focus();
      }
    }
  } else if (which === 37) { // LEFT
    if (isTopLevel(target)) {
      // top level item
      var prevTopItem = adjacentTopLevelItem(target, 'prev');

      if (prevTopItem) {
        keyVent.preventDefault();
        prevTopItem.focus();
      }
    } else {
      // dropdown item
      var prevDropItem = adjacentDropdownItem(target, 'prev');
      if (prevDropItem) {
        keyVent.preventDefault();
        prevDropItem.focus();
      }
    }
  } else if (which === 40) { // DOWN
    if (isTopLevel(target) && hasDropdown(target)) {
      // top level item w/ dropdown -- open dropdown
      openDropdown(target);
    } else {
      // dropdown item
      var nextDropItem = adjacentDropdownItem(target, 'next');

      if (nextDropItem) {
        keyVent.preventDefault();
        nextDropItem.focus();
      }
    }
  } else if (which === 38) { // UP
    if (!isTopLevel(target)) {
      if (isFirstDropItem(target)) {
        keyVent.preventDefault();
        var top = closeDropdown(target);
        setTimeout(function () {
          top.focus();
        }, 0);
      } else {
        var prevDropAnchor = adjacentDropdownItem(target, 'prev');

        if (prevDropAnchor) {
          keyVent.preventDefault();
          prevDropAnchor.focus();
        }
      }
    }
  } else if (which === 27) { // ESCAPE
    if (!isTopLevel(target)) {
      var topper = closeDropdown(target);
      setTimeout(function () {
        topper.focus();
      }, 0);
    }
  } else if (which === 9 && keyVent.shiftKey) { // SHIFT + TAB
    if (!isTopLevel(target) && isFirstDropItem(target)) {
      keyVent.preventDefault();
      var topA = closeDropdown(target);
      setTimeout(function () {
        topA.focus();
      }, 0);
    }
  } else if (which === 9) { // TAB
    if (!isTopLevel(target) && isLastDropItem(target)) {
      keyVent.preventDefault();
      var topItem = closeDropdown(target);
      var nextLi = $(topItem.parentNode).next()[0];
      var nextAnchor = $('a', nextLi)[0];
      nextAnchor.focus();
    }
  } else if (which === 13 || which === 32) {
    if (isTopLevel(target) && $(target.parentNode).hasClass('has-drop')) {
      openDropdown(target);
    }
  }
}

// determines if the item is a top-level one
function isTopLevel(item) {
  return $(item).is('#mega-menu > li > a');
}

// determines if the item has a dropdown
function hasDropdown(item) {
  return $(item.parentNode).hasClass('has-drop');
}

// determines if the item is the first in the dropdown
function isFirstDropItem(item) {
  var drop = $(item).closest('.droplet')[0];
  var firstInDrop = $('li a', drop)[0];

  return firstInDrop === item;

}

// determines if the item is the last in the dropdown
function isLastDropItem(item) {
  var drop = $(item).closest('.droplet')[0];
  var lastInDrop = $('li a', drop).last()[0];

  return lastInDrop === item;
}

// finds the adjacent top level item
function adjacentTopLevelItem(item, dir) {
  var li = item.parentNode; // <li />
  var adjacentLi = (dir === 'next') ?
                    $(li).next()[0] :
                    $(li).prev()[0];
  var adjacentItem = adjacentLi && $('a', adjacentLi)[0];

  return adjacentItem;
}

// finds the next or prev dropdown item
function adjacentDropdownItem(item, dir) {
  var adjacentDropItem;
  var li = item.parentNode;
  var adjacentSameCol = (dir === 'next') ?
                        $(li).next()[0] :
                        $(li).prev()[0];
  if (adjacentSameCol) {
    // there is one in the same col
    adjacentDropItem = $('a', adjacentSameCol)[0];
  } else {
    // lets look for one in the adjacent column
    var col = $(li).closest('.col')[0];
    var adjacentCol = (dir === 'next') ?
                      $(col).next()[0] :
                      $(col).prev()[0];
    if (adjacentCol) {
      // we've found the adjacent column
      var adjacentItem = (dir === 'next') ?
                          $('li a', adjacentCol)[0] :
                          $('li a', adjacentCol).last()[0];

      if (adjacentItem) {
        adjacentDropItem = adjacentItem;
      }
    }
  }

  return adjacentDropItem;
}


function openDropdown(item) {
  $(item.parentNode).addClass('active');
  var droplet = $(item).next()[0];
  // open the dropdown...
  $(droplet).slideDown(100);
  // ...and focus the first item
  setTimeout(function () {
    $('a', droplet)[0].focus();
  }, 100);
}

function closeDropdown(item) {
  var droplet = $(item).closest('.droplet')[0];
  var topLevelItem = $(droplet).prev()[0];
  $(topLevelItem.parentNode).removeClass('active');
  $(droplet).slideUp(100);

  return topLevelItem;
}



////////////////////////////////////
$(document).ready(initMegaMenu);
////////////////////////////////////

CSS Source Code

#mega-menu {
    margin: 0 auto;
    text-align: center;
}

.fa {
    margin-right: 5px;
}

.fa.fa-toggle-down {
    margin-left: 20px;
}

#mega-menu *:focus {
    outline: 4px solid #104BA9;
}

#mega-menu > li.has-drop.active > a {
    background-color: #fff;
    color: #104BA9;
}


#mega-menu .droplet {
    display: none;
    font-size: 14px;
    outline: 3px solid #ccc;
    position: absolute;
	background-color:#fff;
}

h2.col-head {
    margin: 1px;
    padding: 0;
    text-decoration: underline;
}

#mega-menu .droplet .col {
    display: inline-block;
	background-color:#fff;
    vertical-align: top;
    margin: 0 auto;
    padding: 10px;
    text-align: center;
}

#mega-menu .droplet .col ul {
    padding: 5px;
    margin: 0 auto;
    list-style-type: none;
}

#mega-menu .droplet .col a {
    display: block;
    color: #000;
    margin: 0;
    padding: 0;
}

#mega-menu .droplet .col a:focus,
#mega-menu .droplet .col a:hover {
    background-color: #104BA9;
    color: #fff;
}

#mega-menu > li {
    list-style-type: none;
    display: inline-block;
    margin: 5px;
}

#mega-menu > li > a {
    position: relative;
    display: block;
    font-size: 14px;
    text-align: center;
    width: 135px;
    padding: 7px;
    background-color: #ccc;
    text-decoration: none;
    color: #000;
}

#mega-menu > li > a:focus,
#mega-menu > li > a:hover {
    color: #104BA9;
    background-color: #fff;
}

Copy and Paste Full Page Example