Roko Simultaneous Scroll with Wheel and Scrollbar
by thomastthai
HTML
<div class="scrollSyncV" id="a">
Lorem ipsum dolor sit amet, consectetur adipisicing elit.
Consequuntur rerum rem quae iste earum aspernatur.
Laudantium eum, animi maiores unde itaque,
repellat sed magni dicta earum alias, ipsa ad labore!
Deserunt recusandae modi. Earum autem provident eum in officia.
Lorem ipsum dolor sit amet, consectetur adipisicing elit.
Iure possimus doloribus veritatis dolores voluptate quae
fuga eaque mollitia magni nam exercitationem ratione itaque
est debitis dolor, nemo repudiandae voluptas sequi!
<br>
End.
</div>
<div class="scrollSyncV" id="b">
Lorem ipsum dolor sit amet, consectetur adipisicing elit.
Consequuntur rerum rem quae iste earum aspernatur.
Laudantium eum, animi maiores unde itaque,
repellat sed magni dicta earum alias, ipsa ad labore!
<br>End.
</div>
CSS
:root {
padding: 1rem;
}
body {
display: flex;
}
.scrollSyncV {
width: 50%;
height: 10rem;
overflow: auto;
outline: 1px solid black;
box-sizing: border-box;
font-size: 2.5rem;
}
.scrollSyncV div {
border: 10px dashed #aaa;
}
JavaScript
const elsDIV = document.querySelectorAll(".scrollSyncV");
const manualScroll = (evt) => {
const elThis = evt.target;
const elOther = [...elsDIV].filter(e => e !== elThis)[0];
const diff = elThis.scrollTop - elThis._scrollTopOld;
elOther.scrollBy({top: diff});
elThis._scrollTopOld += diff;
};
elsDIV.forEach(el => {
el._scrollTopOld = el.scrollTop;
const elOther = [...elsDIV].filter(e => e !== el)[0];
el.addEventListener("scroll", (evt) => {
evt.preventDefault();
});
el.addEventListener("pointerenter", () => {
el.addEventListener("scroll", manualScroll);
elOther.removeEventListener("scroll", manualScroll);
});
el.addEventListener("wheel", (evt) => {
const delta = Math.sign(evt.deltaY);
console.log(Math.round(el.scrollTop + el.clientHeight), el.scrollHeight)
if( // smaller element cannot scroll any more - continue to scroll the taller one:
delta === -1 && Math.round(el.scrollTop) === 0 ||
delta === 1 && Math.round(el.scrollTop + el.clientHeight) === el.scrollHeight
) {
elOther.scrollBy({top: evt.deltaY, behavior: "smooth"});
}
});
});