<div class="viewport">
<header class="header" role="banner">
<nav id="nav" class="nav" role="navigation">
<!-- ACTUAL NAVIGATION MENU -->
<ul class="nav__menu" id="menu" tabindex="-1" aria-label="main navigation" hidden>
<li class="nav__item"><a href="#" class="nav__link">Home</a></li>
<li class="nav__item"><a href="#" class="nav__link">Shop</a></li>
<li class="nav__item"><a href="#" class="nav__link">Blog</a></li>
<li class="nav__item"><a href="#" class="nav__link">About</a></li>
<li class="nav__item"><a href="#" class="nav__link">Contact</a></li>
</ul>
<!-- MENU TOGGLE BUTTON -->
<a href="#nav" class="nav__toggle" role="button" aria-expanded="false" aria-controls="menu">
<svg class="menuicon" xmlns="http://www.w3.org/2000/svg" width="50" height="50" viewBox="0 0 50 50">
<title>Toggle Menu</title>
<g>
<line class="menuicon__bar" x1="13" y1="16.5" x2="37" y2="16.5"/>
<line class="menuicon__bar" x1="13" y1="24.5" x2="37" y2="24.5"/>
<line class="menuicon__bar" x1="13" y1="24.5" x2="37" y2="24.5"/>
<line class="menuicon__bar" x1="13" y1="32.5" x2="37" y2="32.5"/>
<circle class="menuicon__circle" r="23" cx="25" cy="25" />
</g>
</svg>
</a>
<!-- ANIMATED BACKGROUND ELEMENT -->
<div class="splash"></div>
</nav>
</header>
<!-- DEMO CONTENT -->
<main class="main" role="main">
<div class="gallery" aria-label="gallery">
<a href="#" class="gallery__item"></a>
<a href="#" class="gallery__item"></a>
<a href="#" class="gallery__item"></a>
<a href="#" class="gallery__item"></a>
<a href="#" class="gallery__item"></a>
<a href="#" class="gallery__item"></a>
<a href="#" class="gallery__item"></a>
<a href="#" class="gallery__item"></a>
<a href="#" class="gallery__item"></a>
<a href="#" class="gallery__item"></a>
<a href="#" class="gallery__item"></a>
<a href="#" class="gallery__item"></a>
<a href="#" class="gallery__item"></a>
<a href="#" class="gallery__item"></a>
<a href="#" class="gallery__item"></a>
<a href="#" class="gallery__item"></a>
<a href="#" class="gallery__item"></a>
<a href="#" class="gallery__item"></a>
<a href="#" class="gallery__item"></a>
<a href="#" class="gallery__item"></a>
<a href="#" class="gallery__item"></a>
<a href="#" class="gallery__item"></a>
<a href="#" class="gallery__item"></a>
<a href="#" class="gallery__item"></a>
</div>
</main>
</div>
// ---------------------------
// Vars & Helper Functions
// ---------------------------
:root {
--screen-width: 320px;
--screen-height: 560px;
--header-bg-color: #673AB7;
--splash-bg-color: #368887;
}
// calculate a circle's circumference based on radius
@function circumference($r){
$pi: 3.141592653;
@return 2*$pi*$r;
}
// ---------------------------
// Main Navigation Menu
// ---------------------------
.nav {
// Toggle Button
&__toggle {
display:inline-block;
position:absolute;
z-index:10;
padding:0;
border:0;
background:transparent;
outline:0;
right:15px;
top:15px;
cursor:pointer;
border-radius:50%;
transition:background-color .15s linear;
&:hover,
&:focus {
background-color:rgba(0,0,0,.5);
}
}
&__menu {
display:flex;
flex-direction:column;
justify-content:center;
height:var(--screen-height);
position:relative;
z-index:5;
visibility:hidden;
}
&__item {
opacity:0;
transition: all .3s cubic-bezier(0.000, 0.995, 0.990, 1.000) .3s;
}
@for $i from 1 through 5 {
&__item:nth-child(#{$i}){
transform:translateY(-40px * $i);
}
}
&__link {
color:white;
display:block;
text-align:center;
text-transform:uppercase;
letter-spacing:5px;
font-size:1.25rem;
text-decoration:none;
padding:1rem;
&:hover,
&:focus {
outline:0;
background-color:rgba(0,0,0,0.2);
}
}
}
// ---------------------------
// SVG Menu Icon
// ---------------------------
.menuicon {
display:block;
cursor:pointer;
color: white;
transform:rotate(0deg);
transition: .3s cubic-bezier(0.165, 0.840, 0.440, 1.000);
&__bar,
&__circle {
fill:none;
stroke: currentColor;
stroke-width:3;
stroke-linecap:round;
}
&__bar {
transform: rotate(0deg);
transform-origin:50% 50%;
transition: transform .25s ease-in-out;
}
&__circle {
transition: stroke-dashoffset .3s linear .1s;
stroke-dashoffset:circumference(23); // 23 is the <circle>'s radius
stroke-dasharray:circumference(23);
}
}
// ---------------------------
// Circular Splash Background
// ---------------------------
.splash {
position:absolute;
top:40px;
right:40px;
width: 1px;
height: 1px;
&::after {
content:"";
display:block;
position:absolute;
border-radius:50%;
background-color:var(--splash-bg-color);
// screen diameter can be 142vmax at most,
// circle needs to be twice that size to cover it
width:284vmax;
height:284vmax;
top:-142vmax;
left:-142vmax;
transform: scale(0);
transform-origin:50% 50%;
transition: transform .5s cubic-bezier(0.755, 0.050, 0.855, 0.060);
// will-change tells the browser we plan to
// animate this property in the near future
will-change:transform;
}
}
// ---------------------------
// Active State
// ---------------------------
.nav:target,
.nav--open {
//scale the background circle to full size
> .splash::after {
transform:scale(1);
}
//animate the menu icon
.menuicon {
color:white;
transform:rotate(180deg);
&__circle {
stroke-dashoffset:0;
}
&__bar:nth-child(1),
&__bar:nth-child(4) {
opacity:0;
}
&__bar:nth-child(2) {
transform: rotate(45deg);
}
&__bar:nth-child(3) {
transform: rotate(-45deg);
}
}
//show the nav items
.nav {
&__menu {
visibility:visible;
}
&__item {
opacity:1;
transform:translateY(0);
}
}
}
// ---------------------------
// Demo Stuff, Ignore
// ---------------------------
body {
background-color:#D7D7D7;
font-family: 'Roboto';
min-height:100vh;
display:flex;
flex-direction:column;
justify-content:center;
}
.viewport {
width:var(--screen-width);
height:var(--screen-height);
margin:0 auto;
position:relative;
overflow:hidden;
background-color:white;
}
.header {
height:5rem;
background-color:var(--header-bg-color);
}
.main {
padding:20px;
}
.gallery {
display:grid;
grid-template-columns:repeat(auto-fill, minmax(130px, 1fr));
grid-auto-rows: 130px;
grid-gap:20px;
&__item {
height:100%;
background-color:#D8D8D8;
&:hover,
&:focus {
background-color:#A4A4A4;
}
}
}
View Compiled
const nav = document.querySelector('#nav');
const menu = document.querySelector('#menu');
const menuToggle = document.querySelector('.nav__toggle');
let isMenuOpen = false;
// TOGGLE MENU ACTIVE STATE
menuToggle.addEventListener('click', e => {
e.preventDefault();
isMenuOpen = !isMenuOpen;
// toggle a11y attributes and active class
menuToggle.setAttribute('aria-expanded', String(isMenuOpen));
menu.hidden = !isMenuOpen;
nav.classList.toggle('nav--open');
});
// TRAP TAB INSIDE NAV WHEN OPEN
nav.addEventListener('keydown', e => {
// abort if menu isn't open or modifier keys are pressed
if (!isMenuOpen || e.ctrlKey || e.metaKey || e.altKey) {
return;
}
// listen for tab press and move focus
// if we're on either end of the navigation
const menuLinks = menu.querySelectorAll('.nav__link');
if (e.keyCode === 9) {
if (e.shiftKey) {
if (document.activeElement === menuLinks[0]) {
menuToggle.focus();
e.preventDefault();
}
} else if (document.activeElement === menuToggle) {
menuLinks[0].focus();
e.preventDefault();
}
}
});
View Compiled
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.