JSFiddle - React, Tailwind, and code Playground

by Lianer

HTML

<p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p>

  <div class="scrollTop" id="scrollTop"></div>
  <div class="scrollBottom" id="scrollBottom"></div>

CSS

body{counter-reset: p;}
  p{width: 100px;margin: 20px 0;font: normal 40px/1.5 Arial;text-align: center;border: 1px solid #ccc;}
  p:before{content: counter(p);counter-increment: p;}

  .scrollTop,.scrollBottom{position: fixed;right: 30px;width: 40px;height: 40px;border: 2px solid #1FA879;border-radius: 5px;cursor: pointer;}
  .scrollTop{bottom: 100px;}
  .scrollBottom{bottom: 40px;}
  .scrollTop:before,.scrollBottom:before{content: "";position: absolute;left: 9px;border: 11px solid transparent;}
  .scrollTop:before{top: 3px;border-bottom-color: #1FA879;}
  .scrollBottom:before{top: 15px;border-top-color: #1FA879;}
  .scrollTop:hover,.scrollBottom:hover{background: #1FA879;}
  .scrollTop:hover:before{border-bottom-color: #fff;}
  .scrollBottom:hover:before{border-top-color: #fff;}

JavaScript

(function () {
      var top=document.getElementById("scrollTop"),
          bottom=document.getElementById("scrollBottom"),
          timerTop,timerBottom,timerMove,delayScroll=13,delayMove=23,rate=0.95;

      top.onclick=function () {
        clear(timerTop,timerBottom);
        timerTop=setInterval(function() {
          if(setTop(getPos().st*rate)===0) clear(timerTop);
        }, delayScroll);
      };

      bottom.onclick=function () {
        clear(timerTop,timerBottom);
        timerBottom=setInterval(function() {
          var r=getPos(),_y=Math.ceil((r.sh-r.st-r.ch)*(1-rate));
          if(setTop(_y+r.st)===r.st) clear(timerBottom);
        }, delayScroll);
      };

      top.onmouseover=function () {
        clear(timerMove);
        timerMove=setInterval(function() {
          scrollBy(0,-1);
          if(getPos().st===0) clear(timerMove);
        }, delayMove);
      };

      bottom.onmouseover=function () {
        clear(timerMove);
        timerMove=setInterval(function() {
          scrollBy(0,1);
          var r=getPos();
          if(r.st===r.sh-r.ch) clear(timerMove);
        }, delayMove);
      };

      top.onmouseout=bottom.onmouseout=function () {
        clear(timerMove);
      }

      function getPos() {
        return {
          sh:document.documentElement.scrollHeight,
          ch:document.documentElement.clientHeight||document.body.clientHeight,
          st:window.scrollY||document.documentElement.scrollTop||document.body.scrollTop
        };
      }

      function setTop(s) {
        return document.documentElement.scrollTop=document.body.scrollTop=s;
      }

      function clear() {
        for (var i = 0; i < arguments.length; clearInterval(arguments[i]),i++);
      }
    })();