Om3ga
Om3ga

Reputation: 32823

custom scrollbar using javascript with no plugins

I want to implement a custom scrollbar using javascript. I have following jsfiddle code

JSFIDDLE

<div class="container">
  <ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
    <li>6</li>
    <li>7</li>
    <li>8</li>
    <li>9</li>
    <li>10</li>
  </ul>
</div>

CSS

.container {
  height: 100px;
  width: 100px;
  overflow-y: scroll;
}

It currently has browser's default scrollbar but I want to implement my own with pure javascript. I know there are css3 solutions available but it has browser compatibility issues. There are also plenty of jquery plugins available but my requirement is only javascript.

How can I implement this?

Upvotes: 1

Views: 5402

Answers (1)

Haizhou Liu
Haizhou Liu

Reputation: 491

This is just an quick example. JSFIDDLE here. Please check.

TODO:

  1. Add listener to key event, like up arrow, down arrow and space
  2. Add listener to mouse scroll event.
  3. Drag and drop event on scroll anchor.
  4. Touch event (if touch devices needed to be supported).

Hope this is useful.

UPDATE

Remove jQuery. Got a mistake, didn't read the question very carefully.

var scrollBarContainer = document.getElementById('scroll');
var anchor = document.getElementById('anchor');
var container = document.getElementById('container');
var content = document.querySelectorAll('#container > *:not(#scroll)');

var containerHeight = container.offsetHeight;
var contentHeight = 0;
console.log(content);
for (var i = 0; i < content.length; i++) {
  contentHeight += content[i].scrollHeight;
}

anchor.style.height = Math.floor(containerHeight / contentHeight * containerHeight) + 'px';

var flag_mouseDown = false;
var oldMousePosition = 0;
var oldAnchorPosition = 0;
scrollBarContainer.addEventListener('mousedown', function(e) {
  if (e.target.nodeName === 'DIV') {
    var distance = e.clientY - container.offsetTop - anchor.offsetHeight / 2;
    if (distance < 0) {
      distance = 0;
    } else if (distance + anchor.offsetHeight > containerHeight) {
      distance = containerHeight - anchor.offsetHeight;
    }
    anchor.style.top = distance + 'px';
    moveContent();
  } else if (e.target.nodeName === 'SPAN') {
    flag_mouseDown = true;
    oldMousePosition = e.clientY;
    oldAnchorPosition = anchor.offsetTop;
  }
});
scrollBarContainer.addEventListener('mouseup', function(e) {
  flag_mouseDown = false;
  oldMousePosition = e.clientY;
  oldAnchorPosition = anchor.offsetTop;
});
scrollBarContainer.addEventListener('mousemove', function(e) {
  if (!flag_mouseDown) {
    return;
  }

  var distance = e.clientY - oldMousePosition;
  var newPosition = oldAnchorPosition + distance;

  if (newPosition < 0) {
    newPosition = 0;
  } else if (newPosition + anchor.offsetHeight > containerHeight) {
    newPosition = containerHeight - anchor.offsetHeight;
  }
  anchor.style.top = newPosition + 'px';
  moveContent();
});

var moveContent = function() {
  var postion = anchor.offsetTop / (containerHeight - anchor.offsetHeight);
  var newPosition = (0 - postion * (contentHeight - containerHeight)) + 'px';
  console.log(anchor.offsetTop, container.offsetTop, containerHeight, anchor.offsetHeight);
  console.log(postion, contentHeight, containerHeight);
  for (var i = 0; i < content.length; i++) {
    content[i].style.marginTop = newPosition;
  }
};
.container {
  height: 100px;
  width: 100px;
  overflow-y: hidden;
  position: relative;
  margin-right: 17px;
}
#scroll {
  position: absolute;
  top: 0;
  right: 0;
  width: 17px;
  height: 100%;
  border-left: 1px solid #3e3e3e;
  background-color: #eee;
}
#anchor {
  position: absolute;
  top: 0;
  right: 0;
  width: 17px;
  height: 10px;
  background-color: #aaa;
}
#anchor:hover,
#anchor:active {
  background-color: #333;
}
ul {
  margin: 0;
}
<div id="container" class="container">
  <div id="scroll">
    <span id="anchor"></span>
  </div>
  <ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
    <li>6</li>
    <li>7</li>
    <li>8</li>
    <li>9</li>
    <li>10</li>
  </ul>
</div>

Upvotes: 4

Related Questions