Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Mobile Menu Animation
<div class="page">
<div class="page__demo">
<div class="page__container">
<span class="page__name">Mobile Menu Animation</span>
<span class="page__hint">
Works better on mobile devices. The hamburger button is comfortably available for a lefty and righty.
</span>
<a href="https://www.youtube.com/watch?v=org6Tmfp3PQ" rel="noopener noreferrer" target="_blank">YouTube video with the coding practice</a>
</div>
</div>
</div>
<header class="header">
<div class="hamburger">
<button class="button hamburger__button js-menu__toggle">
<span class="hamburger__label">Open menu</span>
</button>
</div>
<nav class="menu">
<ul class="list menu__list">
<li class="menu__group">
<a href="#0" class="link menu__link">Home</a>
</li>
<li class="menu__group">
<a href="#0" class="link menu__link">About me</a>
</li>
<li class="menu__group">
<a href="#0" class="link menu__link">Services</a>
</li>
<li class="menu__group">
<a href="#0" class="link menu__link">Portfolio</a>
</li>
<li class="menu__group">
<a href="#0" class="link menu__link">Blog</a>
</li>
<li class="menu__group">
<a href="#0" class="link menu__link">Contacts</a>
</li>
</ul>
</nav>
</header>
(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')
});
})();
/*
=====
LEVEL 1. RESET STYLES
=====
*/
button{
border: none;
background-color: transparent;
padding: 0;
font-family: inherit;
}
.button{
cursor: pointer;
color: var(--colorWhite);
}
a{
display:inline-block;
text-decoration: none;
}
.link{
color: inherit;
}
.list{
padding-left: 0;
margin-top: 0;
margin-bottom: 0;
list-style: none;
}
/*
=====
LEVEL 2. MENU STYLES
=====
*/
/* 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;
}
/* hamburger */
.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%;
}
/* activated state */
.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;
}
/*
=====
LEVEL 3. MOBILE ANIMATION STYLES
=====
*/
.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;
}
/*
* demo page
*/
@media (min-width: 768px){
html{
font-size: 62.5%;
}
}
@media (max-width: 767px){
html{
font-size: 50%;
}
}
body{
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Open Sans, Ubuntu, Fira Sans, Helvetica Neue, sans-serif;
font-size: 1.6rem;
color: var(--colorBlack);
margin: 0;
-webkit-overflow-scrolling: touch;
}
:root{
--colorBlack: #222;
--colorWhite: #fff;
--colorGray: #f0f0f0;
--colorMain: #4557bb;
--colorMainLight: #8491d8;
--colorMainDark: #233286;
}
a{
color: var(--colorMain);
}
.page{
min-height: 100vh;
display: flex;
}
.page__demo{
display: flex;
flex-grow: 1;
}
.page__container{
max-width: 370px;
padding: 10px;
margin: auto;
text-align: center;
}
.page__name{
display: block;
font-size: 3rem;
font-weight: 700;
margin-bottom: 1rem;
}
.page__hint{
display: block;
line-height: 1.45;
margin-bottom: .5rem;
}
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.