JSFiddle - React, Tailwind, and code Playground
HTML
<section>
<!-- <button class="start">Scrolling</button> -->
<button class="speed" data-scrolling-speed-increase="10">+10 px/sec</button>
<button class="speed" data-scrolling-speed-increase="-10">-10 px/sec</button>
<button class="speed" data-scrolling-stop="true">stop</button>
<br>
<span id="res"></span>
</section>
<div>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquam repellat nihil placeat, ullam blanditiis iusto
laboriosam quam sunt, quaerat ratione esse quasi eum temporibus voluptas itaque perspiciatis ex mollitia neque.</div>
<div>Sit, quia. Ullam laborum neque voluptates cumque repellendus, minus placeat nihil ab similique optio, cupiditate
architecto sint, esse fugit fuga, incidunt magni tenetur inventore! Laborum non modi culpa consectetur, aliquid!</div>
<div>Vel corrupti officia sit in. Quaerat quo tempore molestias nemo possimus! Earum id obcaecati nam est, maiores
laboriosam velit ut vitae aperiam odit possimus eligendi culpa sunt alias nulla consequatur.</div>
<div>Veritatis consequatur adipisci explicabo in dolor officiis voluptate voluptatibus provident minima itaque ex
suscipit deserunt aspernatur odio, ipsum commodi tempore. Harum odio rerum sit quis ratione voluptate, deserunt
impedit provident.</div>
<div>Explicabo nulla dolores, ipsa perferendis, voluptate laudantium veniam distinctio provident atque, in nobis
natus aspernatur eligendi eius, voluptates? Ullam consequuntur accusamus ducimus dolores velit, facilis vel
molestiae accusantium tempore nulla.</div>
<div>Reiciendis velit error, fuga adipisci, id rem aliquid voluptatum enim quaerat officia, suscipit, incidunt
consectetur. Iure saepe deserunt cum voluptatibus neque praesentium recusandae reprehenderit voluptas, repellat
impedit inventore aspernatur, facilis.</div>
<div>Aliquam repellat, quae odit sequi inventore commodi dignissimos harum a, dicta ex placeat mollitia vitae
voluptates velit...
CSS
div {
width: 300px;
border: 0.1px solid;
margin: auto;
}
section {
position: fixed;
/* top: 30px; */
}
JavaScript
class PageAutoScroll {
constructor() {
this._speed = 0;
this._scrolling = false;
this._scrollTop = this.getScrollTop();
}
getSpeed() {
return this._speed;
}
setSpeed(speed) {
this._speed = speed;
}
incSpeed(inc) {
this.setSpeed(this.getSpeed() + inc);
}
isScrolling() {
return this._scrolling;
}
getScrollTop() {
return document.documentElement.scrollTop || document.body.parentNode.scrollTop || document.body.scrollTop;
}
setScrollTop(amount) {
// because it's so fucking difficult to detect the scrolling element, just move them all
// from https://gist.github.com/james2doyle/5694700
document.documentElement.scrollTop = amount;
document.body.parentNode.scrollTop = amount;
document.body.scrollTop = amount;
}
moveScrollTop(inc) {
this._scrollTop += inc;
this.setScrollTop(this._scrollTop);
}
start() {
this._scrolling = true;
let oldTimestamp = performance.now();
const step = (newTimestamp) => {
const timePassed = newTimestamp - oldTimestamp;
oldTimestamp = newTimestamp;
const scrollDiff = this.getSpeed() * (timePassed / 1000);
this.moveScrollTop(scrollDiff);
if (this.isScrolling()) {
window.requestAnimationFrame(step);
}
}
window.requestAnimationFrame(step);
}
stop() {
this._scrolling = false;
this._speed = 0;
this._scrollTop = this.getScrollTop();
}
}
const pas = new PageAutoScroll();
document.addEventListener('click', e => {
const et = e.target;
if (et.dataset.scrollingSpeedIncrease) {
const increase = parseInt(et.dataset.scrollingSpeedIncrease);
pas.incSpeed(increase);
if (!pas.isScrolling()) pas.start();
res.textContent = pas.getSpeed() + ' px/s';
}
else if (et.dataset.scrollingStop) {
pas.stop();
res.textContent = pas.getSpeed() + ' px/s';
}
});