I am coding for a scrollable website. It runs very well when I use a mouse, but I am facing an issue when using a laptop scroll pad. When I scroll using the laptop pad, these sections move twice as much, which is not good.
I want to each section to be visible only once during a single scroll.
Only code must be in vanilla javascript.
let sections = document.querySelectorAll(".section")
let sectionsWrap = document.getElementById("sections-wrap")
let currentSectionIndex = 0
let isScrolling = false
let scrollToSection = (index) => {
sectionsWrap.style.transform = `translateY(-${index * 100}%)`
sectionsWrap.style.transition = "transform 1s ease-in-out"
}
window.addEventListener("wheel", (event) => {
if (isScrolling) return
if (event.deltaY > 0 && currentSectionIndex < sections.length - 1) {
currentSectionIndex++
} else if (event.deltaY < 0 && currentSectionIndex > 0) {
currentSectionIndex--
} else {
return
}
isScrolling = true
scrollToSection(currentSectionIndex)
setTimeout(() => {
isScrolling = false
}, 1200)
})
html,
body {
margin: 0;
padding: 0;
height: 100%;
overflow: hidden;
}
#sections-wrap {
width: 100%;
height: 100%;
height: 100%;
}
.section {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
font-size: 2rem;
color: white;
}
.section:nth-child(1) {
background: #ff5733;
}
.section:nth-child(2) {
background: #33ff57;
}
.section:nth-child(3) {
background: #3357ff;
}
.section:nth-child(4) {
background: #ff33a1;
}
<div id="sections-wrap">
<div class="section">
<h2>Fist Section</h2>
</div>
<div class="section">
<h2>Second Section</h2>
</div>
<div class="section">
<h2>Third Section</h2>
</div>
<div class="section">
<h2>Fourth Section</h2>
</div>
</div>
Your issue happens because touchpads send multiple scroll events quickly, making sections move too much.
I think it can be fixed by Adding a scroll threshold to detect intentional scrolls and prevent overscrolling like what I did here by changing the wheel
event handler:
let sections = document.querySelectorAll(".section")
let sectionsWrap = document.getElementById("sections-wrap")
let currentSectionIndex = 0
let isScrolling = false
let scrollToSection = (index) => {
sectionsWrap.style.transform = `translateY(-${index * 100}%)`
sectionsWrap.style.transition = "transform 1s ease-in-out"
}
window.addEventListener("wheel", (event) => {
if (isScrolling || Math.abs(event.deltaY) < 20) return; //leave scrolls
if (event.deltaY > 0 && currentSectionIndex < sections.length - 1) {
currentSectionIndex++;
} else if (event.deltaY < 0 && currentSectionIndex > 0) {
currentSectionIndex--;
} else {
return;
}
isScrolling = true;
scrollToSection(currentSectionIndex);
setTimeout(() => (isScrolling = false), 1200);
}, {
passive: false
});
html,
body {
margin: 0;
padding: 0;
height: 100%;
overflow: hidden;
}
#sections-wrap {
width: 100%;
height: 100%;
height: 100%;
}
.section {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
font-size: 2rem;
color: white;
}
.section:nth-child(1) {
background: #ff5733;
}
.section:nth-child(2) {
background: #33ff57;
}
.section:nth-child(3) {
background: #3357ff;
}
.section:nth-child(4) {
background: #ff33a1;
}
<div id="sections-wrap">
<div class="section">
<h2>Fist Section</h2>
</div>
<div class="section">
<h2>Second Section</h2>
</div>
<div class="section">
<h2>Third Section</h2>
</div>
<div class="section">
<h2>Fourth Section</h2>
</div>
</div>