Accessible Expanding Navigation With JavaScript And CSS3

Category: Javascript , Menu & Navigation | October 4, 2017
Author:mxbck
Views Total:364 views
Official Page:Go to website
Last Update:October 4, 2017
License:MIT

Preview:

Accessible Expanding Navigation With JavaScript And CSS3

Description:

An animated accessible navigation that expands the hamburger menu toggle button into a fullscreen navigation menu when toggled.

How to use it:

Insert the navigation menu, menu toggle button, and background element to the web page.

<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>

The primary CSS/CSS3 rules for the navigation.

.nav__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%;
  -webkit-transition: background-color .15s linear;
  transition: background-color .15s linear;
}
.nav__toggle:hover, .nav__toggle:focus { background-color: rgba(0, 0, 0, 0.5); }
.nav__menu {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-orient: vertical;
  -webkit-box-direction: normal;
  -ms-flex-direction: column;
  flex-direction: column;
  -webkit-box-pack: center;
  -ms-flex-pack: center;
  justify-content: center;
  height: var(--screen-height);
  position: relative;
  z-index: 5;
  visibility: hidden;
}
.nav__item {
  opacity: 0;
  -webkit-transition: all 0.3s cubic-bezier(0, 0.995, 0.99, 1) 0.3s;
  transition: all 0.3s cubic-bezier(0, 0.995, 0.99, 1) 0.3s;
}
.nav__item:nth-child(1) {
  -webkit-transform: translateY(-40px);
  transform: translateY(-40px);
}
.nav__item:nth-child(2) {
  -webkit-transform: translateY(-80px);
  transform: translateY(-80px);
}
.nav__item:nth-child(3) {
  -webkit-transform: translateY(-120px);
  transform: translateY(-120px);
}
.nav__item:nth-child(4) {
  -webkit-transform: translateY(-160px);
  transform: translateY(-160px);
}
.nav__item:nth-child(5) {
  -webkit-transform: translateY(-200px);
  transform: translateY(-200px);
}
.nav__link {
  color: white;
  display: block;
  text-align: center;
  text-transform: uppercase;
  letter-spacing: 5px;
  font-size: 1.25rem;
  text-decoration: none;
  padding: 1rem;
}
.nav__link:hover, .nav__link:focus {
  outline: 0;
  background-color: rgba(0, 0, 0, 0.2);
}
.menuicon {
  display: block;
  cursor: pointer;
  color: white;
  -webkit-transform: rotate(0deg);
  transform: rotate(0deg);
  -webkit-transition: 0.3s cubic-bezier(0.165, 0.84, 0.44, 1);
  transition: 0.3s cubic-bezier(0.165, 0.84, 0.44, 1);
}
.menuicon__bar, .menuicon__circle {
  fill: none;
  stroke: currentColor;
  stroke-width: 3;
  stroke-linecap: round;
}
.menuicon__bar {
  -webkit-transform: rotate(0deg);
  transform: rotate(0deg);
  -webkit-transform-origin: 50% 50%;
  transform-origin: 50% 50%;
  -webkit-transition: -webkit-transform .25s ease-in-out;
  transition: -webkit-transform .25s ease-in-out;
  transition: transform .25s ease-in-out;
  transition: transform .25s ease-in-out, -webkit-transform .25s ease-in-out;
}
.menuicon__circle {
  -webkit-transition: stroke-dashoffset .3s linear .1s;
  transition: stroke-dashoffset .3s linear .1s;
  stroke-dashoffset: 144.51326;
  stroke-dasharray: 144.51326;
}
.splash {
  position: absolute;
  top: 40px;
  right: 40px;
  width: 1px;
  height: 1px;
}
.splash::after {
  content: "";
  display: block;
  position: absolute;
  border-radius: 50%;
  background-color: var(--splash-bg-color);
  width: 284vmax;
  height: 284vmax;
  top: -142vmax;
  left: -142vmax;
  -webkit-transform: scale(0);
  transform: scale(0);
  -webkit-transform-origin: 50% 50%;
  transform-origin: 50% 50%;
  -webkit-transition: -webkit-transform 0.5s cubic-bezier(0.755, 0.05, 0.855, 0.06);
  transition: -webkit-transform 0.5s cubic-bezier(0.755, 0.05, 0.855, 0.06);
  transition: transform 0.5s cubic-bezier(0.755, 0.05, 0.855, 0.06);
  transition: transform 0.5s cubic-bezier(0.755, 0.05, 0.855, 0.06), -webkit-transform 0.5s cubic-bezier(0.755, 0.05, 0.855, 0.06);
  will-change: transform;
}
.nav:target > .splash::after, .nav--open > .splash::after {
  -webkit-transform: scale(1);
  transform: scale(1);
}
.nav:target .menuicon, .nav--open .menuicon {
  color: white;
  -webkit-transform: rotate(180deg);
  transform: rotate(180deg);
}
.nav:target .menuicon__circle, .nav--open .menuicon__circle { stroke-dashoffset: 0; }
.nav:target .menuicon__bar:nth-child(1), .nav:target .menuicon__bar:nth-child(4), .nav--open .menuicon__bar:nth-child(1), .nav--open .menuicon__bar:nth-child(4) { opacity: 0; }
.nav:target .menuicon__bar:nth-child(2), .nav--open .menuicon__bar:nth-child(2) {
  -webkit-transform: rotate(45deg);
  transform: rotate(45deg);
}
.nav:target .menuicon__bar:nth-child(3), .nav--open .menuicon__bar:nth-child(3) {
  -webkit-transform: rotate(-45deg);
  transform: rotate(-45deg);
}
.nav:target .nav__menu, .nav--open .nav__menu { visibility: visible; }
.nav:target .nav__item, .nav--open .nav__item {
  opacity: 1;
  -webkit-transform: translateY(0);
  transform: translateY(0);
}

The JavaScript to activate the navigation.

'use strict';
var nav = document.querySelector('#nav');
var menu = document.querySelector('#menu');
var menuToggle = document.querySelector('.nav__toggle');
var isMenuOpen = false;
// TOGGLE MENU ACTIVE STATE
menuToggle.addEventListener('click', function (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', function (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
  var 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();
    }
  }
});

You Might Be Interested In:


Leave a Reply