Home > Enterprise >  Removing onScroll event when menu is clicked
Removing onScroll event when menu is clicked

Time:09-01

When menu is clicked I want it to be fixed not scrollable. How can I remove the event listener on scroll so the menu is staying fixed and scrolling up and down? JavaScript is not my strong skill and if someone with more experience can help me out, it would be greatly appreciated. Thank you

const header = document.querySelector(".hiding-header");
const triggerMenu = document.querySelector(".page-header .trigger-menu");
const nav = document.querySelector(".page-header nav");
const menu = document.querySelector(".page-header .menu");
const scrollUp = "scroll-up";
const scrollDown = "scroll-down";
let lastScroll = 0;

triggerMenu.addEventListener("click", () => {
  header.classList.toggle("menu-open");
});


window.addEventListener("scroll", () => {
  const currentScroll = window.pageYOffset;
  if (currentScroll <= 0) {
    header.classList.remove(scrollUp);
    return;
  }

  if (currentScroll > lastScroll && !header.classList.contains(scrollDown)) {
    // down
    header.classList.remove(scrollUp);
    header.classList.add(scrollDown);
  } else if (
    currentScroll < lastScroll &&
    header.classList.contains(scrollDown)
  ) {
    // up
    header.classList.remove(scrollDown);
    header.classList.add(scrollUp);
  }
  lastScroll = currentScroll;
});
:root {
  --white: #fff;
  --black: #221f1f;
  --lightpurple: #9e91f2;
  --darkgray: #1e1f26;
}

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

button {
  background: transparent;
  border: none;
  cursor: pointer;
  outline: none;
}

ul {
  list-style: none;
}

a {
  text-decoration: none;
  color: inherit;
}

body {
  position: relative;
  font: 16px/1.5 sans-serif;
  color: var(--white);
  -ms-overflow-style: none;
  /* IE and Edge */
  scrollbar-width: none;
  /* Firefox */
}


/* MAIN RULES
–––––––––––––––––––––––––––––––––––––––––––––––––– */

.trigger-menu-wrapper {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  display: flex;
  justify-content: end;
  padding: 20px;
  z-index: 2;
  background: var(--lightpurple);
  transition: transform 0.4s;
}

.page-header .trigger-menu {
  display: flex;
  align-items: center;
  font-size: 1.3rem;
  color: var(--white);
  letter-spacing: 0.2em;
}

.page-header .trigger-menu svg {
  fill: var(--white);
  margin-right: 8px;
  transition: transform 0.3s;
}

.page-header .menu {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  display: none;
  text-align: center;
  padding: 15vh 0 5vh;
  overflow: auto;
  z-index: 1;
  background: var(--lightpurple);
}

.page-header .menu a {
  font-size: 3rem;
}

.page-header .sub-menu a {
  font-size: 1.5rem;
}

.lottie-wrapper {
  position: fixed;
  bottom: 50px;
  right: 25px;
  z-index: 1;
  padding: 5px;
  border-radius: 5px;
}

.page-main section {
  position: relative;
  background-repeat: no-repeat;
  background-position: center;
  background-size: cover;
  height: 100vh;
}

.page-main section::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.25);
}


/* BODY CLASSES
–––––––––––––––––––––––––––––––––––––––––––––––––– */

.menu-open {
  overflow: hidden;
}

.menu-open .trigger-menu-wrapper {
  background: transparent;
  position: fixed;
}

.menu-open .page-header .menu {
  display: block;
}

.menu-open .page-header svg {
  transform: rotate(45deg);
}

.menu-open-with-lottie .page-header .menu {
  padding: 5vh 0;
}

.scroll-down .trigger-menu-wrapper {
  transform: translate3d(0, -100%, 0);
}

.scroll-down .lottie-wrapper {
  background: var(--darkgray);
}

.scroll-up .trigger-menu-wrapper {
  transform: none;
}

.scroll-up:not(.menu-open) .trigger-menu-wrapper {
  background: var(--lightpurple);
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.35);
}


/* FOOTER
–––––––––––––––––––––––––––––––––––––––––––––––––– */

.page-footer {
  position: fixed;
  right: 25px;
  bottom: 10px;
  display: flex;
  align-items: center;
  font-size: 1rem;
  padding: 5px;
  border-radius: 5px;
  background: var(--darkgray);
}

.page-footer a {
  display: flex;
  margin-left: 4px;
}
<script src="https://unpkg.com/@lottiefiles/lottie-player@latest/dist/lottie-player.js"></script>
<header >
  <nav >
    <div >
      <button >
        <svg width="12" height="12" viewBox="0 0 24 24">
          <path d="M24 10h-10v-10h-4v10h-10v4h10v10h4v-10h10z" />
        </svg>
        <span>MENU</span>
      </button>
    </div>
    <ul >
      <li>
        <a href="">About</a>
        <ul >
          <li>
            <a href="">History</a>
          </li>
          <li>
            <a href="">President</a>
          </li>
          <li>
            <a href="">Team</a>
          </li>
          <li>
            <a href="">Process</a>
          </li>
          <li>
            <a href="">Clients</a>
          </li>
        </ul>
      </li>

    </ul>
  </nav>
</header>

<!-- <a href="" role="button" aria-label="Toggle menu" >
  <lottie-player src="https://assets10.lottiefiles.com/datafiles/9gIwZ2uiiKglyb0/data.json" style="width: 60px; height: 60px;"></lottie-player>
</a> -->

<main >
  <section style="background-image:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/162656/freedom.jpg);"></section>
  <section style="background-image:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/162656/travel.jpg);"></section>
  <section style="background-image:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/162656/holidays.jpg);"></section>
</main>

<footer >
  <!-- <span>made by </span>
  <a href="https://georgemartsoukos.com/" target="_blank">
    <img width="24" height="24" src="https://assets.codepen.io/162656/george-martsoukos-small-logo.svg" alt="George Martsoukos logo">
  </a> -->
</footer>

CodePudding user response:

You can use

  removeEventListener(type, listener);

although you may need to make your scroll event a function rather than an anonymous function

const header = document.querySelector(".hiding-header");
const triggerMenu = document.querySelector(".page-header .trigger-menu");
const nav = document.querySelector(".page-header nav");
const menu = document.querySelector(".page-header .menu");
const scrollUp = "scroll-up";
const scrollDown = "scroll-down";
let lastScroll = 0;

triggerMenu.addEventListener("click", () => {
  header.classList.toggle("menu-open");
  window.removeEventListener("scroll", handleScroll)
});


window.addEventListener("scroll", handleScroll);

function handleScroll() {
  const currentScroll = window.pageYOffset;
  if (currentScroll <= 0) {
    header.classList.remove(scrollUp);
    return;
  }

  if (currentScroll > lastScroll && !header.classList.contains(scrollDown)) {
    // down
    header.classList.remove(scrollUp);
    header.classList.add(scrollDown);
  } else if (
    currentScroll < lastScroll &&
    header.classList.contains(scrollDown)
  ) {
    // up
    header.classList.remove(scrollDown);
    header.classList.add(scrollUp);
    }
  lastScroll = currentScroll;
}

CodePudding user response:

To add to @jay's point you cannot call removeEventListener without the original listener function. If you call addEventListener with an anonymous function, you cannot easily remove it, note you could forcibly remove all listeners for DOM elements as mentioned enter image description here

Solution to disable scroll when menu open

Yeah your question was not really about the scroll listener but how to disable the scroll, as you have found out the listener does not stop the scroll just stops listening.

For what you are looking for there are few options the vary in complexity, but the easiest fastest way to make it work is just to add a class to turn scrolling off on the scrolling element.

In you case you are scrolling the document.body, so we need to add a class to the body when the menu is clicked and remove it when it's clicked again to close.

triggerMenu.addEventListener("click", () => {
  header.classList.toggle("menu-open");
   document.body.classList.toggle('disable-scroll'); // <-- add this line
});
body.disable-scroll {
  overflow: hidden; // prevents scrolling on the body
}

See working demo below...

const header = document.querySelector(".hiding-header");
const triggerMenu = document.querySelector(".page-header .trigger-menu");
const nav = document.querySelector(".page-header nav");
const menu = document.querySelector(".page-header .menu");
const scrollUp = "scroll-up";
const scrollDown = "scroll-down";
let lastScroll = 0;


triggerMenu.addEventListener("click", () => {
  header.classList.toggle("menu-open");
  document.body.classList.toggle('disable-scroll');
});


window.addEventListener("scroll", handleScroll);

function handleScroll(e) {
  const currentScroll = window.pageYOffset;
  if (currentScroll <= 0) {
    header.classList.remove(scrollUp);
    return;
  }

  if (currentScroll > lastScroll && !header.classList.contains(scrollDown)) {
    // down
    header.classList.remove(scrollUp);
    header.classList.add(scrollDown);
  } else if (
    currentScroll < lastScroll &&
    header.classList.contains(scrollDown)
  ) {
    // up
    header.classList.remove(scrollDown);
    header.classList.add(scrollUp);
    }
  lastScroll = currentScroll;
}
:root {
  --white: #fff;
  --black: #221f1f;
  --lightpurple: #9e91f2;
  --darkgray: #1e1f26;
}

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

button {
  background: transparent;
  border: none;
  cursor: pointer;
  outline: none;
}

ul {
  list-style: none;
}

a {
  text-decoration: none;
  color: inherit;
}

body {
  position: relative;
  font: 16px/1.5 sans-serif;
  color: var(--white);
   -ms-overflow-style: none;  /* IE and Edge */
  scrollbar-width: none;  /* Firefox */
}

body.disable-scroll {
  overflow: hidden;
}


/* MAIN RULES
–––––––––––––––––––––––––––––––––––––––––––––––––– */
.trigger-menu-wrapper {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  display: flex;
  justify-content: end;
  padding: 20px;
  z-index: 2;
  background: var(--lightpurple);
  transition: transform 0.4s;
}

.page-header .trigger-menu {
  display: flex;
  align-items: center;
  font-size: 1.3rem;
  color: var(--white);
  letter-spacing: 0.2em;
}

.page-header .trigger-menu svg {
  fill: var(--white);
  margin-right: 8px;
  transition: transform 0.3s;
}

.page-header .menu {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  display: none;
  text-align: center;
  padding: 15vh 0 5vh;
  overflow: auto;
  z-index: 1;
  background: var(--lightpurple);
}

.page-header .menu a {
  font-size: 3rem;
}

.page-header .sub-menu a {
  font-size: 1.5rem;
}

.lottie-wrapper {
  position: fixed;
  bottom: 50px;
  right: 25px;
  z-index: 1;
  padding: 5px;
  border-radius: 5px;
}

.page-main section {
  position: relative;
  background-repeat: no-repeat;
  background-position: center;
  background-size: cover;
  height: 100vh;
}

.page-main section::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.25);
}


/* BODY CLASSES
–––––––––––––––––––––––––––––––––––––––––––––––––– */
.menu-open {
  overflow: hidden;
}

.menu-open .trigger-menu-wrapper {
  background: transparent;
  position: fixed;
}

.menu-open .page-header .menu {
  display: block;
}

.menu-open .page-header svg {
  transform: rotate(45deg);
}

.menu-open-with-lottie .page-header .menu {
  padding: 5vh 0;
}

.scroll-down .trigger-menu-wrapper {
  transform: translate3d(0, -100%, 0);
}

.scroll-down .lottie-wrapper {
  background: var(--darkgray);
}

.scroll-up .trigger-menu-wrapper {
  transform: none;
}

.scroll-up:not(.menu-open) .trigger-menu-wrapper {
  background: var(--lightpurple);
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.35);
}


/* FOOTER
–––––––––––––––––––––––––––––––––––––––––––––––––– */
.page-footer {
  position: fixed;
  right: 25px;
  bottom: 10px;
  display: flex;
  align-items: center;
  font-size: 1rem;
  padding: 5px;
  border-radius: 5px;
  background: var(--darkgray);
}

.page-footer a {
  display: flex;
  margin-left: 4px;
}
<script src="https://unpkg.com/@lottiefiles/lottie-player@latest/dist/lottie-player.js"></script>
<header >
  <nav >
    <div >
      <button >
        <svg width="12" height="12" viewBox="0 0 24 24">
          <path d="M24 10h-10v-10h-4v10h-10v4h10v10h4v-10h10z" />
        </svg>
        <span>MENU</span>
      </button>
    </div>
    <ul >
      <li>
        <a href="">About</a>
        <ul >
          <li>
            <a href="">History</a>
          </li>
          <li>
            <a href="">President</a>
          </li>
          <li>
            <a href="">Team</a>
          </li>
          <li>
            <a href="">Process</a>
          </li>
          <li>
            <a href="">Clients</a>
          </li>
        </ul>
      </li>

    </ul>
  </nav>
</header>

<!-- <a href="" role="button" aria-label="Toggle menu" >
  <lottie-player src="https://assets10.lottiefiles.com/datafiles/9gIwZ2uiiKglyb0/data.json" style="width: 60px; height: 60px;"></lottie-player>
</a> -->

<main >
  <section style="background-image:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/162656/freedom.jpg);"></section>
  <section style="background-image:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/162656/travel.jpg);"></section>
  <section style="background-image:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/162656/holidays.jpg);"></section>
</main>

<footer >
  <!-- <span>made by </span>
  <a href="https://georgemartsoukos.com/" target="_blank">
    <img width="24" height="24" src="https://assets.codepen.io/162656/george-martsoukos-small-logo.svg" alt="George Martsoukos logo">
  </a> -->
</footer>

Note: The biggest issues with approach is the scroll bars/width of the page can snap back and forth creating a jarring UI twitch. The second is that it clears the user scroll height, if they scroll to the bottom then open the menu and close it the scroll would jump back to the top. Since you hide the menu unless the user is at the top this doesn't matter in your case. The other issue is not noticeable in this case.

  • Related