JavaScript Menu

JavaScript Menu
Project: Simple toggle menu in vanilla Javascript
Author: jacmaes
Edit Online: View on CodePen
License: MIT

This JavaScript code snippet helps you to create a menu. In this code a className property of the document.documentElement object to “js”, adds an event listener to the button element and defines a function to close the menu when the user clicks outside of it. The button. on click function toggles the “menu-active” class on the menu element using the class.toggle method. The event listener is defined in the document.addEventListener function checks whether the clicked element is not the dropdown element and its descendant and removes the “menu-active” class from the menu element using the class.removeClass method. The code also includes a self-invoking function that defines the class object, which provides several helper methods for manipulating CSS classes in the DOM, including hasClass, addClass, removeClass, and toggleClass.

How to Create JavaScript Menu

First of all, load the following assets into the head tag of your HTML document.

<meta name="viewport" content="width=device-width, initial-scale=1">

Create the HTML structure for the menu as follows:

<nav class="dropdown">
  <button class="nav-toggle"><svg viewBox="0 0 16 16"><path d="M8.5 1c-4.142 0-7.5 3.358-7.5 7.5 0 4.143 3.358 7.5 7.5 7.5 4.143 0 7.5-3.357 7.5-7.5 0-4.142-3.357-7.5-7.5-7.5zm4 11h-8c-.276 0-.5-.225-.5-.5s.224-.5.5-.5h8c.275 0 .5.225.5.5s-.225.5-.5.5zm0-3h-8c-.276 0-.5-.225-.5-.5 0-.276.224-.5.5-.5h8c.275 0 .5.224.5.5 0 .275-.225.5-.5.5zm0-3h-8c-.276 0-.5-.224-.5-.5s.224-.5.5-.5h8c.275 0 .5.224.5.5s-.225.5-.5.5z"/></svg> Menu</button>
  <ul class="menu">
    <li><a href="#0">one</a></li>
    <li><a href="#0">two</a></li>
    <li><a href="#0">three</a></li>
    <li><a href="#0">four</a></li>
    <li><a href="#0">five</a></li>
  </ul>
</nav>

Style the menu using the following CSS styles:

body {
  width:15em;
  margin:5em auto;
  font:1em sans-serif;
  background:#222;
}

.dropdown {
  padding:1em 1em 0 1em;
  background:turquoise;
  display:block;
  color:#222;
}

.nav-toggle {
  -webkit-appearance: none;
  background:white;
  text-transform:uppercase;
  font-size:1em;
  padding:.5em;
  border:none;
  outline:none;
  transition: all 0.2s;
  cursor:pointer;
}

.nav-toggle:hover {
  background:#222;
  color:#fff;
}

.nav-toggle:focus, .menu a:focus {
  outline:1px solid red;
}

.nav-toggle svg {
  width:16px;   
  height:16px;
  fill:red;
  vertical-align:top;
  margin-right:.25em;
}

.menu {
  list-style:none;
  padding:0;
  margin:1em 0 0 0;
  transition: all 0.8s cubic-bezier(.15,.7,0,1);
}

.menu a {
  display:block;
  color:turquoise;
  background:#222;
  text-decoration:none;
  padding:.5em .5em;
  outline:none;
  margin-bottom:.2em;
  transition: all 0.2s;
}


.menu a:hover {
  background:#fff;
  color:#222;
}

.js .menu {
		overflow: hidden;
		max-height: 0;
}

.js .menu-active {
	max-height:12em;
  padding-bottom:1em;
}

Load the following scripts before closing the body tag:

<script src='https://raw.githubusercontent.com/desandro/classie/master/classie.js'></script>

Finally, add the following JavaScript function for its functionality:

document.documentElement.className = "js";

var menu = document.querySelector( '.menu' ),
    button = document.querySelector('.nav-toggle'),
    dropdown = document.querySelector('.dropdown');

button.onclick = function() {
    classie.toggle( menu, 'menu-active' );
};

// Close menu when clicking outside
// See: https://css-tricks.com/dangers-stopping-event-propagation/
document.addEventListener('click', function(event) {
    if (event.target !== dropdown && !dropdown.contains(event.target)) {
        // hide the menu
      classie.removeClass(menu, "menu-active");
    }
});


/*!
 * classie v1.0.1
 * class helper functions
 * from bonzo https://github.com/ded/bonzo
 * MIT license
 *
 * classie.has( elem, 'my-class' ) -> true/false
 * classie.add( elem, 'my-new-class' )
 * classie.remove( elem, 'my-unwanted-class' )
 * classie.toggle( elem, 'my-class' )
 */

/*jshint browser: true, strict: true, undef: true, unused: true */
/*global define: false, module: false */

( function( window ) {

'use strict';

// class helper functions from bonzo https://github.com/ded/bonzo

function classReg( className ) {
  return new RegExp("(^|\\s+)" + className + "(\\s+|$)");
}

// classList support for class management
// altho to be fair, the api sucks because it won't accept multiple classes at once
var hasClass, addClass, removeClass;

if ( 'classList' in document.documentElement ) {
  hasClass = function( elem, c ) {
    return elem.classList.contains( c );
  };
  addClass = function( elem, c ) {
    elem.classList.add( c );
  };
  removeClass = function( elem, c ) {
    elem.classList.remove( c );
  };
}
else {
  hasClass = function( elem, c ) {
    return classReg( c ).test( elem.className );
  };
  addClass = function( elem, c ) {
    if ( !hasClass( elem, c ) ) {
      elem.className = elem.className + ' ' + c;
    }
  };
  removeClass = function( elem, c ) {
    elem.className = elem.className.replace( classReg( c ), ' ' );
  };
}

function toggleClass( elem, c ) {
  var fn = hasClass( elem, c ) ? removeClass : addClass;
  fn( elem, c );
}

var classie = {
  // full names
  hasClass: hasClass,
  addClass: addClass,
  removeClass: removeClass,
  toggleClass: toggleClass,
  // short names
  has: hasClass,
  add: addClass,
  remove: removeClass,
  toggle: toggleClass
};

// transport
if ( typeof define === 'function' && define.amd ) {
  // AMD
  define( classie );
} else if ( typeof exports === 'object' ) {
  // CommonJS
  module.exports = classie;
} else {
  // browser global
  window.classie = classie;
}

})( window );

That’s all! hopefully, you have successfully integrated the JavaScript code for the menu. If you have any questions or suggestions, feel free to comment below.

Leave a Comment

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

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