
A mobile-first fullscreen hamburger navigation system that uses CSS3 transforms to achieve the morphing effects when opening and closing.
How to use it:
Create the navigation menu and hamburger menu toggle as follows:
<header class="header">
<div class="hamburger">
<button class="button hamburger__button js-menu__toggle">
<span class="hamburger__label">Launch</span>
</button>
</div>
<nav class="menu">
<ul class="list menu__list">
<li class="menu__group">
<a href="#" class="link menu__link">Menu Item 1</a>
</li>
<li class="menu__group">
<a href="#" class="link menu__link">Menu Item 2</a>
</li>
<li class="menu__group">
<a href="#" class="link menu__link">Menu Item 3</a>
</li>
<li class="menu__group">
<a href="#" class="link menu__link">Menu Item 4</a>
</li>
<li class="menu__group">
<a href="#" class="link menu__link">Menu Item 5</a>
</li>
...
</ul>
</nav>
</header>The primary CSS styles for the menu.
.header{
box-sizing: border-box;
width: 100%;
color: var(--colorWhite);
display: flex;
justify-content: center;
position: fixed;
bottom: 0;
left: 0;
z-index: 9998;
}
.menu{
box-sizing: border-box;
width: 100%;
padding-bottom: 55px;
height: 0;
transform: translate3d(0, -100%, 0);
opacity: 0;
display: flex;
align-items: flex-end;
position: fixed;
top: 0;
left: 0;
}
.menu__list{
box-sizing: border-box;
width: 100%;
max-height: 100%;
display: none;
padding-top: 30px;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
}
.menu__group{
padding: .5rem 3rem;
font-size: 3.2rem;
font-weight: 700;
text-transform: uppercase;
}
.menu__group_active{
background-color: var(--colorWhite);
color: var(--colorBlack);
}
.menu__item{
padding: 8px 25px;
display: block;
}Style the hamburger menu toggle button.
.hamburger{
position: relative;
line-height: 1;
padding-bottom: .5em;
}
.hamburger:before{
content :"";
width: 100px;
height: 100px;
background-color: var(--colorMain);
border-radius: 50%;
position: absolute;
bottom: -55px;
left: -35px;
}
.hamburger__button{
width: 1.4em;
height: 1em;
font-size: 20px;
position: relative;
text-indent: -9999px;
z-index: 2;
}
.hamburger__button:before, .hamburger__button:after, .hamburger__label{
width: 100%;
height: 20%;
border-radius: 5px;
background-color: currentColor;
position: absolute;
left: 0;
}
.hamburger__button:before, .hamburger__button:after{
content:"";
}
.hamburger__button:before{
top: 0;
}
.hamburger__button:after{
bottom: 0;
}
.hamburger__button:focus{
outline: none;
}
.hamburger__label{
margin-top: -.1em;
top: 50%;
}The required CSS styles for the menu when activated.
.js-menu_activated{
overflow: hidden;
}
.js-menu_activated .menu{
height: 100%;
transform: translate3d(0, 0, 0);
opacity: 1;
}
.js-menu_activated .hamburger:before{
width: 100vh;
height: 100vh;
transform: translate3d(-50vh, -50vh, 0) scale(5);
}
.js-menu_activated .menu__list{
display: block;
}
.js-menu_activated .hamburger__button:before{
transform: translate3d(0, -50%, 0) rotate(45deg);
top: 50%;
}
.js-menu_activated .hamburger__button:after{
transform: translate3d(0, -50%, 0) rotate(135deg);
top: 50%;
}
.js-menu_activated .hamburger__label{
transform: rotate(-45deg) translate3d(-5.71429px,-6px,0);
opacity: 0;
}The CSS for the morphing effects.
.menu{
transition: opacity .2s ease-out;
}
.js-menu_activated .menu{
will-change: opacity;
transition-duration: .2s;
transition-delay: .3s;
}
.hamburger:before{
will-change: width, height;
transition: transform .3s cubic-bezier(0.04, -0.1, 0.29, 0.98),
width .3s cubic-bezier(0.04, -0.1, 0.29, 0.98),
height .3s cubic-bezier(0.04, -0.1, 0.29, 0.98);
}
.js-menu_activated .hamburger:before{
transition-duration: 1s;
}
.hamburger__button:before, .hamburger__button:after{
transition-property: transform;
}
.hamburger__button:before, .hamburger__button:after, .hamburger__label{
transition-timing-function: ease;
transition-duration: .15s;
}
.hamburger__label{
transition-property: transform, opacity;
}The main JavaScript to toggle CSS classes when you toggle the menu.
(function(){
'use strict';
class Menu {
constructor(settings) {
this.nodeMenu = settings.nodeMenu;
settings.nodeMenuButton.addEventListener('click', this.toggle.bind(this));
}
toggle() {
return this.nodeMenu.classList.toggle('js-menu_activated');
}
}
let nodeMenu = document.querySelector('body');
new Menu({
nodeMenu: nodeMenu,
nodeMenuButton: nodeMenu.querySelector('.js-menu__toggle')
});
})();






