Search code examples
javascripthtmlcssmobilenav

Event listener not firing for some reason


I've adapted the code from Simply-Nav (great lightweight mobile nav – thanks obscuredetour) so that the background semi-transparent overlay fades in as opposed to sliding in with the nav.

Got that working fine, but what I've lost now is the ability to click/tap the semi-transparent overlay (on the right hand side) to close the whole nav.

The event listener is still there – pageOverlay.addEventListener('click', toggleNav); – but it's not firing pageOverlay.classList.remove('-open');.

The overlay div is no longer a child of the parent <ul class="nav-list">, so I don't know if that has something to do with it.

I've tried creating a transparent overlay over the overlay div, and add an eventlistener to that, but that hasn't worked.

Here's the code, if anyone has any ideas, I'd be really grateful for any help. I'm still a novice, so no doubt it's something obvious. Thanks so much.

/*
  simply-nav.js - v1.2.1
  https://github.com/obscuredetour/simply-nav

  Licensed MIT © Jeffrey Summers
*/

// This anonymous function can be inserted anywhere
// (eg. within a <script> tag or anywhere in an existing .js file)
(simplyNavDuty => {

  const sideNav = document.querySelector('.nav-list'),
    toggleNavBtn = document.querySelector('.toggle-nav'),
    burger = document.querySelector('.burger'),
    pageOverlay = document.querySelector('.overlay'),
    navLinks = document.querySelectorAll(".link"),
    body = document.querySelector('body'),
    html = document.querySelector('html');

  // Disable page scroll
  function disablePageScroll() {
    if (sideNav.classList.contains('-open')) {
      body.classList.add('_disableScroll');
      html.classList.add('_disableScroll');
    } else {
      body.classList.remove('_disableScroll');
      html.classList.remove('_disableScroll');
    }
  };

  // Nav funtion (toggle)
  function toggleNav() {
    sideNav.classList.toggle('-open');
    pageOverlay.classList.toggle('-open');
    burger.classList.toggle('open');
    disablePageScroll();
  };

  // To default
  toDefaults = () => {
    // Close nav menu
    sideNav.classList.remove('-open');
    pageOverlay.classList.remove('-open');
    burger.classList.remove('open');
    // Make sure scrolling is enabled
    body.classList.remove('_disableScroll');
    html.classList.remove('_disableScroll');
  }

  // Event listeners
  toggleNavBtn.addEventListener('click', toggleNav);
  pageOverlay.addEventListener('click', toggleNav);

  // (on mobile) close nav menu when link is clicked
  // this is useful on mobile when clicking an anchor tag on the current page (eg. index.html#last-section)
  navLinks.forEach(el => {
    el.addEventListener('click', (event) => {
      toDefaults();
    });
  });


  // when browser is resized (past breakpoint) reset to defaults
  (function() {

    window.addEventListener("resize", resizeThrottler, false);
    let resizeTimeout;

    function resizeThrottler() {
      // ignore resize events as long as an actualResizeHandler execution is in the queue
      if (!resizeTimeout) {
        resizeTimeout = setTimeout(function() {
          resizeTimeout = null;
          actualResizeHandler();

          // The actualResizeHandler will execute at a rate of 15fps
        }, 66);
      }
    }

    function actualResizeHandler() {
      // handle the resize event

      // Window resized width
      let width = window.innerWidth;

      // If resized greater than BREAKPOINT (default: 800px), then reset nav functions
      if (width >= 800) {
        toDefaults();
      }
    }

  }());


})();
/*******HAMBURGER TOGGLE*******/

.toggle-nav {
  background-color: transparent;
  cursor: pointer;
  box-shadow: none;
  border: 0;
  outline: none;
  margin: 0;
  padding: 3vh;
}

.logo-link {
  z-index: 2;
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 0.5rem;
}

.logo-link>.logo {
  max-width: 60px;
  width: 100%;
  height: auto;
  backface-visibility: hidden;
  transform-style: preserve-3d;
  -webkit-backface-visibility: hidden;
  -webkit-transform-style: preserve-3d;
  transition: max-height 0.2s ease-in-out;
  -webkit-transition: max-height 0.2s ease-in-out;
}


/*******HAMBURGER TOGGLE*******/

.nav-list {
  background-color: transparent;
  list-style: none;
  margin: 0;
  padding: 0;
  display: block;
  position: absolute;
  top: 10vh;
  bottom: 0;
  left: -50rem;
  width: 60%;
  min-height: 100vh;
  -webkit-overflow-scrolling: touch;
  transition: all 0.3s ease-in-out;
  backface-visibility: hidden;
  transform-style: preserve-3d;
  -webkit-backface-visibility: hidden;
  -webkit-transform-style: preserve-3d;
  z-index: 6;
}

.nav-list.-open {
  width: 100%;
  left: 0;
  padding-bottom: 4.5rem;
}

.nav-list.-open>.list.-left {
  overflow-y: auto;
  overscroll-behavior-y: auto;
  -webkit-overflow-scrolling: touch;
}

.nav-list>.list.-left {
  background: rgba(50, 31, 101, 0.95);
  position: relative;
  width: 60%;
  height: 100%;
}

.overlay {
  margin: 0;
  padding: 0;
  display: block;
  min-height: 100vh;
  background: rgb(0 0 0 / 65%);
  position: absolute;
  bottom: 0;
  width: 100%;
  top: 10vh;
  cursor: pointer;
  z-index: 5;
  -webkit-overflow-scrolling: touch;
  transition: all 0.3s ease-in-out;
  backface-visibility: hidden;
  transform-style: preserve-3d;
  -webkit-backface-visibility: hidden;
  -webkit-transform-style: preserve-3d;
  visibility: hidden;
  opacity: 0;
  transition: visibility 0s, opacity 0.3s linear;
}

.toggle-overlay {}

.overlay.-open {
  visibility: visible;
  opacity: 1;
}


/****** LIST ITEMS ******/

.nav-list>.list>.item {
  display: flex;
  padding: 0;
  border-bottom: 1px solid rgba(176, 176, 176, 0.5);
}

.nav-list>.list>.item:last-child {
  border-bottom: 0;
}

.nav-list>.list>.item>.link {
  border-color: transparent;
  text-decoration: none;
  padding: 1.5rem 1rem 1.5rem 1rem;
  flex-basis: 100%;
  display: block;
  background: transparent;
  font-size: 1.5rem;
  padding-left: 1.5rem;
  color: #e0e0e0;
  transition: all 0.3s ease-in-out;
}

.nav-list>.list>.item>.link:hover,
.nav-list>.list>.item>.link.-active {
  color: #e90052;
}

._disableScroll {
  overflow-y: hidden !important;
}


/***********BURGER BUTTON STYLES***********/

.burger {
  height: 3em;
  width: 3em;
  position: relative;
  font-size: 10px;
  cursor: pointer;
  -webkit-transition: .2s all;
  -o-transition: .2s all;
  transition: .2s all;
}

.burger:after {
  content: '';
  display: block;
  position: absolute;
  height: 150%;
  width: 150%;
  top: -25%;
  left: -25%;
}

.burger>.burger-lines {
  top: 50%;
  margin-top: -0.125em;
}

.burger>.burger-lines:before {
  left: 0;
  top: 1em;
}

.burger>.burger-lines:after {
  left: 0;
  top: -1em;
}

.burger.-offset>.burger-lines {
  top: 50%;
  margin-top: -0.125em;
}

.burger.-offset>.burger-lines:before {
  left: 1em;
  top: 1em;
}

.burger.-offset>.burger-lines:after {
  left: 0;
  top: -1em;
}

.burger.-squeeze .burger-lines,
.burger.-squeeze .burger-lines:before,
.burger.-squeeze .burger-lines:after {
  -webkit-transition: .2s top .2s, .1s left, .2s transform, .4s background-color .2s;
  -o-transition: .2s top .2s, .1s left, .2s transform, .4s background-color .2s;
  transition: .2s top .2s, .1s left, .2s transform, .4s background-color .2s;
}

.burger.-squeeze .burger-lines:after {
  left: 0;
  top: -1em;
}

.burger.-squeeze .burger-lines:before {
  left: 0;
  top: 1em;
}

.burger.-squeeze.-offset .burger-lines:before,
.burger.-squeeze.-offset .burger-lines:after {
  width: 2em;
}

.burger.-squeeze.-offset .burger-lines:after {
  left: 0;
  top: -1em;
}

.burger.-squeeze.-offset .burger-lines:before {
  left: 1em;
  top: 1em;
}

.burger.-squeeze.open .burger-lines,
.burger.-squeeze.open .burger-lines:before,
.burger.-squeeze.open .burger-lines:after {
  -webkit-transition: .2s background-color, .2s top, .2s left, .2s transform .15s;
  -o-transition: .2s background-color, .2s top, .2s left, .2s transform .15s;
  transition: .2s background-color, .2s top, .2s left, .2s transform .15s;
}

.burger.-squeeze.open .burger-lines {
  background-color: transparent;
}

.burger.-squeeze.open .burger-lines:before,
.burger.-squeeze.open .burger-lines:after {
  left: 0.5em;
  top: 0px;
}

.burger.-squeeze.open .burger-lines:before {
  -webkit-transform: rotate(-45deg);
  -ms-transform: rotate(-45deg);
  transform: rotate(-45deg);
}

.burger.-squeeze.open .burger-lines:after {
  -webkit-transform: rotate(45deg);
  -ms-transform: rotate(45deg);
  transform: rotate(45deg);
}

.burger-lines,
.burger-lines:after,
.burger-lines:before {
  pointer-events: none;
  display: block;
  content: '';
  width: 100%;
  border-radius: 0.25em;
  background-color: #e0e0e0;
  height: 0.25em;
  position: absolute;
  -webkit-transform: rotate(0);
  -ms-transform: rotate(0);
  transform: rotate(0);
}

.burger.-squeeze>.burger-lines {
  top: 50%;
  margin-top: -0.125em;
}

.burger.-squeeze>.burger-lines,
.burger.-squeeze>.burger-lines:after,
.burger.-squeeze>.burger-lines:before {
  transition: .2s top .2s, .1s left, .2s transform, .4s background-color .2s;
}

.burger.-squeeze>.burger-lines:after {
  left: 0;
  top: -1em;
}

.burger.-squeeze>.burger-lines:before {
  left: 0;
  top: 1em;
}

.burger.-squeeze.-offset>.burger-lines,
.burger.-squeeze.-offset>.burger-lines:after,
.burger.-squeeze.-offset>.burger-lines:before {
  transition: .2s top .2s, .1s left, .2s transform, .4s background-color .2s;
}

.burger.-squeeze.-offset>.burger-lines:after,
.burger.-squeeze.-offset>.burger-lines:before {
  width: 2em;
}

.burger.-squeeze.-offset>.burger-lines:after {
  left: 0;
  top: -1em;
}

.burger.-squeeze.-offset>.burger-lines:before {
  left: 1em;
  top: 1em;
}

.burger.-squeeze.open>.burger-lines,
.burger.-squeeze.open>.burger-lines:after,
.burger.-squeeze.open>.burger-lines:before {
  transition: .2s background-color, .2s top, .2s left, .2s transform .15s;
}

.burger.-squeeze.open>.burger-lines:after,
.burger.-squeeze.open>.burger-lines:before {
  width: 2em;
}

.burger.-squeeze.open>.burger-lines {
  background-color: transparent;
}

.burger.-squeeze.open>.burger-lines:before,
.burger.-squeeze.open>.burger-lines:after {
  left: 0.5em;
  top: 0px;
}

.burger.-squeeze.open>.burger-lines:before {
  transform: rotate(-45deg);
}

.burger.-squeeze.open>.burger-lines:after {
  transform: rotate(45deg);
}
<header>
  <button class="toggle-nav" type="button">
        <div class="burger -squeeze -offset" type="button">
          <span class="burger-lines"></span>
        </div>
      </button>

  <ul class="nav-list" role="navigation">
    <div class="list -left">
      <li class="item">
        <a class="link" href="#">Menu item 1</a>
      </li>
      <li class="item">
        <a class="link" href="#">Menu item 2</a>
      </li>
      <li class="item">
        <a class="link" href="#">Menu item 3</a>
      </li>
      <li class="item">
        <a class="link" href="#">Menu item 4</a>
      </li>
    </div>
  </ul>
  <div class="overlay"></div>
</header>


Solution

  • That actually looks like a css problem. The tag <ul class="nav-list -open"> has a width of 100%, and for that reason it fills up the whole screen, not allowing the mouse click to get to the overlay element. You should:

    • remove width: 100% on the -open class (the source of the problems)
    • remove width: 60% on the .list.-left (The child of the nav doesn't fill it, it doesn't make too much sense...)
    • set left: -80rem instead of 50rem in .nav-list (to fully hide it)

    That would make it work.