Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Expanding and Collapsing Hamburger Menu

Expanding and Collapsing Hamburger Menu

Experimenting with making the menu items themselves collapse into the bars of the hamburger menu.

A Pen by Jon Wilcox on CodePen.

License.

<nav class="menu">
<header>Menu <span>×</span></header>
<ol>
<li class="menu-item"><a href="#0">Home</a></li>
<li class="menu-item"><a href="#0">About</a></li>
<li class="menu-item">
<a href="#0">Widgets</a>
<ol class="sub-menu">
<li class="menu-item"><a href="#0">Big Widgets</a></li>
<li class="menu-item"><a href="#0">Bigger Widgets</a></li>
<li class="menu-item"><a href="#0">Huge Widgets</a></li>
</ol>
</li>
<li class="menu-item">
<a href="#0">Kabobs</a>
<ol class="sub-menu">
<li class="menu-item"><a href="#0">Shishkabobs</a></li>
<li class="menu-item"><a href="#0">BBQ kabobs</a></li>
<li class="menu-item"><a href="#0">Summer kabobs</a></li>
</ol>
</li>
<li class="menu-item"><a href="#0">Contact</a></li>
</ol>
<footer><button aria-label="Toggle Menu">Toggle</button></footer>
</nav>
var $els = $('.menu a, .menu header');
var count = $els.length;
var grouplength = Math.ceil(count/3);
var groupNumber = 0;
var i = 1;
$('.menu').css('--count',count+'');
$els.each(function(j){
if ( i > grouplength ) {
groupNumber++;
i=1;
}
$(this).attr('data-group',groupNumber);
i++;
});
$('.menu footer button').on('click',function(e){
e.preventDefault();
$els.each(function(j){
$(this).css('--top',$(this)[0].getBoundingClientRect().top + ($(this).attr('data-group') * -15) - 20);
$(this).css('--delay-in',j*.1+'s');
$(this).css('--delay-out',(count-j)*.1+'s');
});
$('.menu').toggleClass('closed');
e.stopPropagation();
});
// run animation once at beginning for demo
setTimeout(function(){
$('.menu footer button').click();
setTimeout(function(){
$('.menu footer button').click();
}, (count * 100) + 500 );
}, 1000);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
@import url("https://fonts.googleapis.com/css?family=Open+Sans:400,400i,700");
* {
font-family: 'Open Sans', sans-serif;
box-sizing: border-box;
color: #333;
font-size: 100%;
line-height: 1.5;
}
body {
background: #9fcedf;
margin: 0;
}
nav {
--duration: .5s;
--easing: ease-in-out;
position: relative;
width: 220px;
margin: 20px;
ol {
list-style-type: none;
margin: 0;
padding: 0;
}
li {
margin: -4px 0 0 0;
}
a {
display: block;
text-decoration: none;
background: #fff;
transform-origin: 0 0;
transition: transform var(--duration) var(--easing), color var(--duration) var(--easing);
transition-delay: var(--delay-out);
border-radius: 4px;
padding: 1em 1.52em;
&:hover {
background: #efefef;
}
}
.sub-menu {
a {
font-size: .9em;
color: #666666;
border-left: 2em solid white;
padding: .75em;
background: linear-gradient(
to right,
#ddd 2px,
#fff 2px
);
&:hover {
background: linear-gradient(
to right,
#ddd 2px,
#efefef 2px
);
}
}
}
header {
font-weight: 600;
display: block;
background: rgba(255,255,255,.5);
transform-origin: 0 0;
transition: transform var(--duration) var(--easing), color var(--duration) var(--easing);
transition-delay: var(--delay-out);
border-radius: 4px;
padding: 1em 1.52em;
span {
border: none;
background: transparent;
font-size: 1.5em;
padding: 0;
cursor: pointer;
line-height: 1;
float: right;
}
}
footer button {
position: absolute;
top: 0;
left: 0;
border: none;
padding: calc(~'1em - 2px');
width: 100%;
transform-origin: 0 0;
transition: transform var(--duration) var(--easing);
transition-delay: calc(~'var(--duration) + (.1s * (var(--count) / 2))');
cursor: pointer;
outline: none;
background: #cdcdcd;
opacity: 0;
}
&.closed {
a, header {
transform: translateY(~'calc(var(--top) * -1)') scaleY(0.1) scaleX(.2);
transition-delay: var(--delay-in);
color: transparent;
}
footer button {
transition-delay: 0s;
transform: scaleY(.7) scaleX(.2);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.