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