Vertical menu collapsible v2
by Plippie Plop
HTML
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
<aside><nav id="list">
<ul class="menu">
<li class="first-menu"><a>Item 1</a></li>
<li class="first-menu"><a>Item 2</a>
<ul>
<li><a>item 2 sub 1</a></li>
<li><a>Item 2 sub 2</a></li>
</ul>
</li>
<li class="first-menu"><a>Item 3</a>
<ul>
<li><a>item 3 sub 1</a></li>
<li><a>Item 3 sub 2</a>
<ul>
<li><a>Item 2 sub-sub 1</a></li>
<li><a>Item 2 sub-sub 2</a></li>
</ul>
</li>
<li><a>Item 3 sub 3</a>
<li><a>Item 3 sub 4</a>
<li><a>Item 3 sub 5</a>
<li><a>Item 3 sub 6</a>
</ul>
</li>
<li class="first-menu"><a>Item 4</a>
<ul>
<li><a>item 4 sub 1</a></li>
<li><a>Item 4 sub 2</a>
<ul>
<li><a>Item 4 sub-sub 1</a></li>
<li><a>Item 4 sub-sub 2</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</nav>
</aside>
CSS
@import url('https://fonts.googleapis.com/css2?family=Oswald&display=swap');
:root {
--menu-bg: rgb(250, 250, 250);
--menu-item-bg: rgb(255, 255, 255);
--menu-item-hover-bg: rgb(242, 242, 245);
--menu-item-active-bg: rgb(124 192 251);
--menu-item-active-hover-bg: rgb(171 214 251);
--menu-color: rgb(20,20,20);
--menu-active-color: rgb(255,255,255);
--menu-border-radius: 0;
--menu-sub-height: 20em;
/* using font awesome 4.7 for chevron icons */
}
* {
box-sizing: border-box;
}
aside{
position:absolute;
left:0;
top:0;
bottom:0;
background-color:lightgrey;
}
#list ::-webkit-scrollbar {
width: 0.25rem;
}
#list ::-webkit-scrollbar-track {
background: var(--memu-bg);
}
#list ::-webkit-scrollbar-thumb {
background: rgba(100, 100, 100, 0.4);
border-radius: 2px;
}
#list ::-webkit-scrollbar-thumb:hover {
background: rgba(100, 100, 100, 0.8);
}
ul,
li {
margin: 0;
padding: 0;
list-style: none;
position: relative;
outline: none;
overflow: hidden;
}
#list {
display: flex;
position: relative;
width: fit-content;
font-family: "Oswald";
border-radius: var(--menu-border-radius);
min-width: 200px;
box-shadow: -5px 5px 11px 0 rgba(0, 0, 0, 0.18);
}
.menu {
width: 100%;
}
.menu ul {
max-height: 0;
transition: max-height 0.2s;
height: auto;
background-color: var(--menu-bg);
}
.menu li.open>ul {
transition: max-height 0.2s;
max-height: var(--menu-sub-height);
overflow-y: auto;
border-bottom: 1px solid rgba(0, 0, 0, 0.3);
border-top: 1px solid rgba(0, 0, 0, 0.3);
}
.menu a {
display: flex;
border-bottom: 1px solid rgba(0, 0, 0, 0.2);
padding: 0.5rem 1.5rem 0.5rem 0.5rem;
cursor: pointer;
position: relative;
color: var(--menu-color);
background-color: var(--menu-item-bg);
}
.menu a:hover {
background-color: var(--menu-item-hover-bg);
}
.menu li a.active {
background-color: var(--menu-item-active-bg);
color: var(--menu-active-color);
}
.menu a.active:hover {
...
JavaScript
const list = $("#list");
list.find('a').each(function(idx, elm) {
console.log(idx, elm);
$(elm).closest('li').attr('data-menu-index', idx);
if ($(elm).closest('li').children('ul').length) {
$(elm).closest('li').addClass('has-sub');
}
});
list.find('.active').parents('li').addClass('open').find('> a').addClass('active');
list.on('click', 'a', function(e) {
let $this = $(this);
if (!$this.hasClass('active')) {
console.log("not active");
list.find('.open').removeClass('open');
list.find('.active').removeClass('active');
$this.addClass('active').parents('li').addClass('open').find('> a').addClass('active');
} else {
console.log("IS active");
$this.removeClass('active').closest('li').removeClass('open');
$this.children('li').removeClass('open');
}
});