multi level dropdown menu: vertical & horizontal dropdown menu
(function(){
function $(selector, context){
context = context || document;
return context["querySelectorAll"](selector);
}
function forEach(collection, iterator){
for(var key in Object.keys(collection)){
iterator(collection[key]);
}
}
function showMenu(menu){
var menu = this;
var ul = $("ul", menu)[0];
if(!ul || ul.classList.contains("-visible")) return;
menu.classList.add("-active");
ul.classList.add("-animating");
ul.classList.add("-visible");
setTimeout(function(){
ul.classList.remove("-animating")
}, 25);
}
function hideMenu(menu){
var menu = this;
var ul = $("ul", menu)[0];
if(!ul || !ul.classList.contains("-visible")) return;
menu.classList.remove("-active");
ul.classList.add("-animating");
setTimeout(function(){
ul.classList.remove("-visible");
ul.classList.remove("-animating");
}, 300);
}
function hideAllInactiveMenus(menu){
var menu = this;
forEach(
$("li.-hasSubmenu.-active:not(:hover)", menu.parent),
function(e){
e.hideMenu && e.hideMenu();
}
);
}
window.addEventListener("load", function(){
forEach($(".Menu li.-hasSubmenu"), function(e){
e.showMenu = showMenu;
e.hideMenu = hideMenu;
});
forEach($(".Menu > li.-hasSubmenu"), function(e){
e.addEventListener("mouseover", showMenu);
});
forEach($(".Menu > li.-hasSubmenu li"), function(e){
e.addEventListener("mouseenter", hideAllInactiveMenus);
});
forEach($(".Menu > li.-hasSubmenu li.-hasSubmenu"), function(e){
e.addEventListener("mouseenter", showMenu);
});
document.addEventListener("click", hideAllInactiveMenus);
});
})();
/*
Naming convention:
Block
element
-modifier
*/
.Menu {
display: none;
position: relative;
}
/* Three basic menu layouts */
/* This also enforces that menu is a ul, and that
* layout modifier is specified
*/
ul.Menu.-horizontal,
ul.Menu.-vertical {
display: inline-block;
}
ul.Menu.-floating {
display: block;
position: absolute;
}
/* Menu and menu-item layout */
.Menu,
.Menu li,
.Menu li > ul {
list-style: none;
padding: 0px;
margin: 0px;
}
.Menu li {
display: block;
position: relative;
white-space: nowrap;
word-break: keep-all;
}
.Menu.-horizontal > li {
display: inline-block;
float: left;
}
.Menu li > * {
display: block;
position: relative;
}
.Menu li > ul {
position: absolute;
min-width: 100%;
top: 0px;
left: 100%;
}
.Menu.-horizontal.-alignRight li > ul {
left: auto;
right: 100%;
}
.Menu.-horizontal.-alignRight > li > ul {
right: 0px;
}
.Menu.-horizontal > li > ul {
top: auto;
left: auto;
}
/* Menu behaviour */
.Menu li > ul,
.Menu.-floating {
display: none;
}
.Menu li > ul.-visible,
ul.Menu.-floating.-visible {
display: block;
}
/* Menu animation */
.Menu li > ul,
.Menu.-horizontal.-alignRight li > ul,
.Menu.-floating {
opacity: 1;
transform: scale(1) translateY(0px);
transform-origin: left top;
}
.Menu.-alignRight li > ul,
.Menu.-floating.-alignRight {
transform-origin: right top;
}
.Menu li > ul.-animating,
.Menu.-floating.-animating {
opacity: 0 !important;
transform: scale(0.96) translateX(-16px);
}
.Menu li > ul.-animating {
z-index: -1 !important;
}
.Menu.-horizontal > li > ul.-animating {
transform: scale(0.96) translateY(-16px);
}
.Menu.-alignRight li > ul.-animating,
.Menu.-floating.-alignRight.-animating {
transform: scale(0.96) translateX(16px);
}
.Menu.-horizontal.-alignRight > li > ul.-animating {
transform: scale(0.96) translateY(-16px);
}
/* Menu item icons */
.Menu *[data-icon]:before {
position: absolute;
left: 0px;
top: 0px;
bottom: 0px;
margin: auto 0px;
}
.Menu .Icon,
.Menu *[data-icon]:before {
line-height: inherit;
}
.Menu .Icon {
padding: 0px;
}
.Menu *:empty[data-icon] {
padding-left: 0px !important;
padding-right: 0px !important;
}
/* Submenu chevrons */
.Menu li.-hasSubmenu > a:after {
display: block;
position: absolute;
width: 8px;
height: 8px;
right: 8px;
bottom: 0px;
top: 0px;
margin: auto 0px;
transform: rotate(45deg);
border-width: 1px;
border-color: black;
border-style: solid solid none none;
content: "";
}
.Menu.-horizontal > li.-hasSubmenu > a:after {
width: 4px;
height: 4px;
bottom: 4px;
top: auto;
left: 0px;
right: 0px;
margin: 0px auto;
border-style: none solid solid none;
}
.Menu li.-hasSubmenu.-noChevron > a:after {
display: none;
}
/*
** Configurable values
*/
/* Height of navbar, and menu items */
/* All of these must be of equal value */
.Menu {
line-height: 40px;
}
.Menu.-horizontal,
.Menu li,
.Menu li > :first-child {
height: 40px;
}
.Menu *[data-icon]:before,
.Menu .Icon {
width: 40px;
height: 40px;
}
.Menu *[data-icon] {
min-width: 40px;
min-height: 40px;
padding-left: 40px;
}
/* Default font settings for menu */
.Menu {
font-family: Arial, Helvetica, Sans;
font-size: 16px;
}
/* Icon font sizes */
.Menu *[data-icon]:before,
.Menu .Icon {
font-size: 24px;
}
/* For submenus */
.Menu > li ul .Icon,
.Menu.-floating .Icon,
.Menu > li ul *[data-icon]:before,
.Menu.-floating *[data-icon]:before,
{
font-size: 18px;
}
/* Colouring of menus */
/* Foreground */
.Menu,
.Menu li.-hasSubmenu > a:after {
color: black;
border-color: black; /* chevron colour */
}
/* Background */
.Menu ul,
.Menu.-floating {
background: white;
}
/* Padding for each menu item */
.Menu li > * {
padding: 0px 12px;
}
/* Indent of chevron */
.Menu li li.-hasSubmenu > a:after,
.Menu:not(.-horizontal) > li.-hasSubmenu > a:after {
right: 12px;
}
.Menu li li.-hasSubmenu > a,
.Menu:not(.-horizontal) > li.-hasSubmenu > a {
padding-right: 28px;
}
/* Minimum width of dropdown menus */
.Menu.-horizontal li > ul,
.Menu.-floating {
min-width: 200px;
}
/* Animation speed of dropdown menus */
.Menu li > ul,
.Menu.-floating {
transition: width 0.1s, height 0.1s, transform 0.1s, opacity 0.1s;
}
/* Styling of hyperlink text */
.Menu li > a {
text-decoration: none;
color: inherit;
}
/* Animation speed of :hover shading */
.Menu li > a:first-child {
transition: background-color 0.2s;
}
/* Colour of :hover shading */
.Menu li:hover > a:first-child,
.Menu li.-active > a:first-child {
background-color: rgba(0,0,0,0.1);
}
/*
** End configurable values
*/
<!--
https://www.cssscript.com/multi-level-dropdown-menu-pure-javascript-tidy-menu/
-->
<link rel="stylesheet" href="menu.css">
<script src="menu.js"></script>
<!-- MENU HTML
note:
- vertical: class="Menu -vertical"
- horizontal: class="Menu -horizontal"
-->
<ul class="Menu -horizontal">
<li class="-hasSubmenu -noChevron"> <a href="#" data-icon="apps"></a>
<ul>
<li><a href="#">Bacon</a></li>
<li><a href="#">Ipsum</a></li>
<li><a href="#">Dolor</a></li>
<li><a href="#">Amet</a></li>
</ul>
</li>
<li class="-hasSubmenu"> <a href="#">Alpha</a>
<ul>
<li><a href="#">Bacon</a></li>
<li><a href="#">Ipsum</a></li>
<li class="-hasSubmenu"> <a href="#">Sub-menu</a>
<ul>
<li><a href="#">Bacon</a></li>
<li><a href="#">Ipsum</a></li>
<li><a href="#">Dolor</a></li>
<li><a href="#">Amet</a></li>
</ul>
</li>
<li><a href="#">Dolor</a></li>
<li><a href="#">Amet</a></li>
<li class="-hasSubmenu"> <a href="#">Another Sub-menu</a>
<ul>
<li><a href="#">Bacon</a></li>
<li><a href="#">Ipsum</a></li>
<li class="-hasSubmenu"> <a href="#">Sub-sub-menu!</a>
<ul>
<li><a href="#">Bacon</a></li>
<li><a href="#">Ipsum</a></li>
<li><a href="#">Dolor</a></li>
<li><a href="#">Amet</a></li>
</ul>
</li>
<li><a href="#">Dolor</a></li>
<li><a href="#">Amet</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#">Beta</a></li>
<li class="-hasSubmenu"> <a href="#">Gamma</a>
<ul>
<li><a href="#" data-icon="">Ipsum</a></li>
<li class="-hasSubmenu"> <a data-icon="cast" href="#">Dolorsssssssssssssssssssssssss</a>
<ul>
<li><a href="#">Bacon</a></li>
<li><a href="#">Ipsum</a></li>
<li><a href="#">Dolor</a></li>
<li><a href="#">Amet</a></li>
</ul>
</li>
<li><a href="#" data-icon="">Amet</a></li>
<li><a href="#" data-icon="cake">Tail pork loin chicken</a></li>
<li><a href="#" data-icon="">Bacon ipsum dolor amet pork loin rump filet mignon swine</a></li>
</ul>
</li>
<li><a href="#">Delta</a></li>
<li><a href="#">Epsilon</a></li>
</ul>