JSFiddle - React, Tailwind, and code Playground
HTML
<div id="header">
<p>header</p>
</div>
<div id="docnav">
<button id="up">Up</button>
<div id="sidescroll">
<div id="sidescrollbtn"></div>
</div>
<button id="down">Down</button><br><br>
<button id="top">Go to Top</button><br><br>
</div>
<div id="maincontent">
<p id="wheight">0</p>
<p id="dheight">0</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
<p>content</p>
</div>
<div id="footer">
<p>Footer</p>
</div>
CSS
#header{width:100%;background:red;height:100px;}
#docnav{position:fixed;right:0,width:10%;background:red;right:8px;text-align:center;}
#sidescroll{padding: 10px 0 0;position: relative; height:80px;width:10px;background:grey;border:1px solid black;margin:0 auto;}
#sidescrollbtn{position: relative;height:10px;width:10px;background:red;}
#maincontent{border:1px solid black;background-color:lightblue;width:500px;margin:0 0 100px 20px;}
#footer{height:100px;width:100%;background:red;position:fixed;bottom:0;}
JavaScript
var vh,
dh,
timer,
scrollBound;
// This is a short hand for "document ready".
$(function() {
// Bind Events when DOM is ready
// Note the chaining!
$(document).on('mousedown', '#up, #down', _scroller)
.on('mouseup', _scroller)
.on('mousewheel DOMMouseScroll', _handleWheel);
$('#top').on('click', _scrollTop);
// Determine btn height
vh = document.documentElement.clientHeight;
dh = document.documentElement.scrollHeight;
$('#sidescrollbtn').css('height', 80 * ((vh > dh ? dh : vh) / dh));
});
// Event handler for clicking up/down. The logic is passed to our _scroll handler.
// In this function, we are setting a flag that will notify the document when a user
// lets go of the mouse button.
function _scroller(evt) {
// Because both event handlers are bound to the _scroller function, we'll check
// against the event type. We assume mouseup clears the interval (preventing the
// weird jerky scrolling you mentioned.
if (evt.type === 'mousedown') {
// Here we check against the element to see if the user is clicking "UP"
if ($(evt.target).is($('#up'))) {
// Our interval, which passes -1 to our scroll logic
timer = setInterval(function() {
_scroll(-1);
}, 100);
} else {
// Our interval, which passes 1 to our scroll logic
timer = setInterval(function() {
_scroll(1);
}, 100);
}
// Flag scroller flag.
scrollBound = true;
}
// This is the logic that runs when the user lets go of the mouse (mouseup)
// We make sure the flag was set, and if so, we clear the interval.
else if (scrollBound) {
clearInterval(timer);
}
}
// Our scroll logic. The only difference is the direction - so we pass a 1/-1
// to handle our calculations. In addition, I addressed an issue with the...