<nav class="nav" data-nav id="nav">
<ul class="nav__items">
<li class="nav__item">
<a href="/" data-item>Services</a>
</li>
<li class="nav__item">
<a href="/" data-item>Cases</a>
</li>
<li class="nav__item">
<a href="/" data-item>Careers</a>
</li>
<li class="nav__item">
<a href="/" data-item>Contact</a>
</li>
</ul>
</nav>
<a class="toggle" href="#" data-toggle>Navigation</a>
*,
*:before,
*:after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html,
body {
width: 100%;
height: 100%;
}
body {
font-family: sans-serif;
background-color: #fffeca;
}
.nav {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: #ffe400;
transform: translateX(-100%);
}
.nav__items {
padding: 20px;
list-style: none;
}
.nav__item {
display: flex;
justify-content: center;
overflow: hidden;
}
.nav__item a {
display: block;
padding-top: 10px;
padding-bottom: 10px;
font-size: 1.6rem;
color: #00f;
text-decoration: none;
transform-origin: 100% 50%;
will-change: transform;
}
.toggle {
position: fixed;
right: 20px;
bottom: 20px;
width: 40px;
height: 40px;
background-color: #00f;
overflow: hidden;
text-indent: 60px;
}
View Compiled
const nav = document.querySelector('[data-nav]')
const items = [...nav.querySelectorAll('[data-item]')]
const toggle = document.querySelector('[data-toggle]')
const reducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches
const duration = reducedMotion ? .01 : 400
const stagger = reducedMotion ? 0 : 50
const easing = 'cubic-bezier(.17,.67,.35,.98)'
let initial
let totalDuration = duration
const animations = []
animations.push(
nav.animate({
transform: ['translateX(-100%)', 'translateX(0%)'],
offset: 0
}, {
duration,
fill: 'both',
easing
})
)
items.forEach((item, index) => {
animations.push(
item.animate({
transform: ['translateY(150%) rotate(-15deg)', 'translateY(0%) rotate(0deg)'],
offset: 0
},{
duration,
delay: duration * .5 + index * stagger,
fill: 'both',
easing
})
)
})
animations.forEach(animation => animation.pause())
function handleToggle(event) {
event.preventDefault()
if(!initial) {
animations.forEach(item => item.play())
initial = true
} else {
animations.forEach(item => item.reverse())
}
}
toggle.addEventListener('click', handleToggle)
View Compiled
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.