JSFiddle - React, Tailwind, and code Playground

by João Vitor Scheuermann

HTML

<div id="contentWrapper">
  <div id="content"></div>
</div>


<div class="scrollTrack">
  <div class="scrollGrip"></div>
</div>

CSS

#contentWrapper {
  display: inline-block;
  position: relative;
  height: 200px;
  width: 500px;
  background: #f0f0f0;
  overflow-y: hidden;
}

#contentWrapper #content {
  height: 400px;
  width: 100%;
  background: linear-gradient(#e66465, #9198e5);
}

.scrollTrack {
  display: inline-block;
  position: relative;
  height: 500px;
  width: 10px;
  background: #f0f0f0;
  overflow-y: scroll;
  border-radius: 5px;
  vertical-align: top;
}

.scrollTrack .scrollGrip {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  background: #888888;
  border-radius: 5px;
}

.scrollTrack .scrollGrip:active {
  background: #999999;
}

JavaScript

// Set of the variables used in the calculus
let windowSize = 200
let contentSize = 400

// Determine how large our track is
let trackSize = 500
// ISSO PODE VIRAR UMA FUNÇAO. OU UMA PROPRIEDADE COMPUTADA
// calculates the viewContentRatio
let windowContentRatio = windowSize / contentSize // SÓ É UTILIZADO PRA CALCULAR O TAMANHO DO GRIP :D

// Multiply the trackSize by the ratio to determine how large our grip will be
let gripSize = trackSize * windowContentRatio

// The minimal size of our grip
let minGripSize = 20
if (gripSize < minGripSize) gripSize = minGripSize

// The maximum size of our grip
let maxGripSize = trackSize
if (gripSize > maxGripSize) gripSize = maxGripSize

document.querySelector('.scrollGrip').style.height = gripSize + 'px'

// AREAS DOS SCROLLS
// Determina quanto a window pode scrollar
/*
 * Determina quanto a window pode scrollar
 * equivalente ao scrollableWidth e scrollableHeight
 */
let windowScrollAreaSize = contentSize - windowSize
// tamanho total da area que o grip pode ser scrollado.
let trackScrollAreaSize = trackSize - gripSize

/*
 * Posição do window no track
 * equivalente ao scrollTop e scrollLeft
 */
let windowPosition = 0

// posição do grip

let gripPositionOnTrack = 0

// VARIAVEIS PARA O MOUSE MOVE
let oldMousePosition = null
let newMousePosition = null
let mousePositionDelta = null

function handleMouseMove (e) {
	newMousePosition = e.clientY
	mousePositionDelta = newMousePosition - oldMousePosition
  
  // calcula a nova posição do grip
  let newGripPosition = gripPositionOnTrack + mousePositionDelta  
  
  // Limita a posição do grip aos limites da area de track
  if (newGripPosition < 0) newGripPosition = 0
  if (newGripPosition > trackScrollAreaSize) newGripPosition = trackScrollAreaSize
  
  // Seta a posição do grip na variavel para ser reutilizado e depois aplica no DOM
  gripPositionOnTrack = newGripPosition  
  document.querySelector('.scrollGrip').style.top = gripPositionOnTrack + 'px'
  
  // calcula o ratio...