Author: | Dannie Vinther |
---|---|
Views Total: | 1,031 views |
Official Page: | Go to website |
Last Update: | December 11, 2017 |
License: | MIT |
Preview:

Description:
A high-performance morphing navigation concept that reveals a fullscreen navigation menu as you click/tap on the hamburger toggle button. Built with plain JavaScript and CSS/CSS3.
How to use it:
Create the hamburger menu toggle button.
<div id="nav-bg" class="btn"></div> <div id="toggle-btn" class="btn"> <span></span> <span></span> <span></span> </div>
Insert the navigation menu into your main content.
<div class="wrapper"> <nav> <ul> <li><a class="link" href="#">Home</a></li> <li><a class="link" href="#">About</a></li> <li><a class="link" href="#">Contact</a></li> </ul> </nav> <div id="content"> More content here </div> </div>
The CSS styles for the navigation background.
#nav-bg { transform-origin: center center; transition: transform .3s; transform: translate(var(--translate-x), var(--translate-y)) scale(var(--scale)); will-change: transform; pointer-events: none; }
Style the toggle button.
.btn { position: fixed; height: calc(var(--btn-size)*1px); width: calc(var(--btn-size)*1px); bottom: calc((var(--offset-value))*1px); left: calc(var(--offset-value)*1px); /*left: calc(50% - (var(--btn-size)/2*1px)); if you wish to center it */ border-radius: 50%; background: #fafafa; cursor: pointer; margin: 0; padding: 0 15px; border: none; z-index: 100; user-select: none; -webkit-tap-highlight-color: rgba(0,0,0,0); } #toggle-btn { display: flex; flex-direction: column; justify-content: center; align-items: center; color: var(--green); /*box-shadow: 0 6px 12px rgba(0,0,0,.1);*/ transition: transform .3s; } #toggle-btn span { position: relative; width: 100%; } #toggle-btn span { margin-top: -4px; } #toggle-btn span + span { margin-top: 8px; } #toggle-btn span:before, #toggle-btn span:after { content: ''; position: absolute; top: 0; background: currentColor; opacity: .8; height: 100%; width: 50%; height: 4px; transition: .25s cubic-bezier(.6,0,.3,1); transform-origin: center center; } #toggle-btn span:before { left: 0; border-radius: 3px 0 0 3px; } #toggle-btn span:after { right: 0; border-radius: 0 3px 3px 0; } #toggle-btn.shown span:nth-of-type(1):before { transform: translate3d(3px, 3.5px, 0) rotate(45deg); } #toggle-btn.shown span:nth-of-type(1):after { transform: translate3d(-3px, 3.5px, 0) rotate(-45deg); } #toggle-btn.shown span:nth-of-type(3):before { transform: translate3d(3px, -3.5px, 0) rotate(-45deg); } #toggle-btn.shown span:nth-of-type(3):after { transform: translate3d(-3px, -3.5px, 0) rotate(45deg); } #toggle-btn.shown span:nth-of-type(2):before, #toggle-btn.shown span:nth-of-type(2):after { opacity: 0; } #toggle-btn.shown span:nth-of-type(2):before { transform: translateX(-200%); } #toggle-btn.shown span:nth-of-type(2):after { transform: translateX(200%); } #toggle-btn.shown:before { transform: scale(.6); transition: .2s; } #toggle-btn:before { content: ''; transition: .2s .2s; position: absolute; top: 3px; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,.1); border-radius: inherit; filter: blur(5px); z-index: -2; } #toggle-btn:after { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 100%; border-radius: inherit; background: #fafafa; z-index: -1; }
The main CSS for the navigation menu.
nav { width: 100%; height: 100%; background: transparent; position: fixed; top: 0; left: 0; overflow: hidden; display: flex; z-index: 200; pointer-events: none; } nav ul { margin: auto; pointer-events: auto; text-align: center; } nav li { font-size: 30px; color: #212121; user-select: none; transform: translate(-20px,20px) scale(.9); transition: 0s; opacity: 0; visibility: hidden; will-change: transform; } nav li + li { margin-top: 30px; } #toggle-btn.shown ~ .wrapper nav li { transform: none; opacity: 1; visibility: visible; transition: .35s cubic-bezier(.4,2.08,.55,1); } #toggle-btn.shown ~ .wrapper nav li:nth-child(1) { transition-delay: .15s; } #toggle-btn.shown ~ .wrapper nav li:nth-child(2) { transition-delay: .125s; } #toggle-btn.shown ~ .wrapper nav li:nth-child(3) { transition-delay: .1s; }
The main JavaScript.
var elem = document.querySelector('#nav-bg'), toggleBtn = document.querySelector('#toggle-btn'), elemH = elem.getBoundingClientRect().height, elemW = elem.getBoundingClientRect().width; var open = false; var scale = undefined, offsetX = undefined, offsetY = undefined; var calculateValues = function calculateValues() { var w = window.innerWidth; var h = window.innerHeight; //const cssStyles = getComputedStyle(elem); //const offsetValue = Number(cssStyles.getPropertyValue('--offset-value')); var offsetValue = Number(getComputedStyle(elem).getPropertyValue('--offset-value')); // Offsets to center the circle offsetX = w / 2 - elemW / 2 - offsetValue; offsetY = h / 2 - elemH / 2 - offsetValue; // Good old pythagoras var radius = Math.sqrt(Math.pow(h, 2) + Math.pow(w, 2)); scale = radius / (elemW / 2) / 2 + .1; // Add '.1' to compensate for Safari sub pixel blur issue return scale; }; var openMenu = function openMenu() { elem.style.setProperty("--translate-x", offsetX + 'px'); elem.style.setProperty("--translate-y", '-' + offsetY + 'px'); elem.style.setProperty("--scale", scale); }; var closeMenu = function closeMenu() { elem.style.setProperty("--scale", 1); elem.style.setProperty("--translate-x", 0); elem.style.setProperty("--translate-y", 0); }; var animateMenu = function animateMenu() { open ? openMenu() : closeMenu(); }; var toggleMenu = function toggleMenu() { open = !open; animateMenu(); toggleBtn.classList.toggle('shown'); }; var resizeHandler = function resizeHandler() { window.requestAnimationFrame(function () { calculateValues(); animateMenu(); }); }; calculateValues(); //toggleBtn.onclick = toggleMenu; toggleBtn.addEventListener('click', toggleMenu, false); window.addEventListener("resize", resizeHandler, false);