1

I said “JavaScript”. I'm trying to make my own JavaScript custom scrollbar. It's almost successful. The problem is that I can't get an accurate multiplier for the scrolling speed. This is my code:

var elem = document.getElementById('scroll-area'),
    track = elem.children[1],
    thumb = track.children[0],
    height = parseInt(elem.offsetHeight, 10),
    cntHeight = parseInt(elem.children[0].offsetHeight, 10),
    trcHeight = parseInt(track.offsetHeight, 10),
    distance = cntHeight - height,
    mean = 50, // For multiplier (go faster or slower)
    current = 0;

elem.children[0].style.top = current + "px"; // Set default `top` value as `0` for initiation
thumb.style.height = Math.round(trcHeight * height / cntHeight) + 'px'; // Set the scrollbar thumb hight

var doScroll = function (e) {

    // cross-browser wheel delta
    e = window.event || e;
    var delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));

    // (1 = scroll-up, -1 = scroll-down)
    // Always check the scroll distance, make sure that the scroll distance value will not
    // increased more than the content height and/or less than zero
    if ((delta == -1 && current * mean >= -distance) || (delta == 1 && current * mean < 0)) {
        current = current + delta;
    }

    // Move element up or down by updating the `top` value
    elem.children[0].style.top = (current * mean) + 'px';
    thumb.style.top = 0 - Math.round(trcHeight * (current * mean) / cntHeight) + 'px';

    e.preventDefault();

};

if (elem.addEventListener) {
    elem.addEventListener("mousewheel", doScroll, false);
    elem.addEventListener("DOMMouseScroll", doScroll, false);
} else {
    elem.attachEvent("onmousewheel", doScroll);
}

And the markup:

<div id="scroll-area">
    <div><!-- CONTENT --></div>
    <span class="scrollbar-track"><span class="scrollbar-thumb"></span></span>
</div>

My problem is on mean = 50. When you scroll the container until the bottom of content, the red line that I made in the demo page should stop right at the bottom of the container, not higher than that.

Anyone have an idea for the accurate result?

PS: I also want to add a function that will enable user to scroll the content by dragging the scrollbar thumb. But I think I want to focus on this issue first. Thanks for your help.

DEMO: http://jsfiddle.net/tovic/2B8Ye/

1 Answer 1

2

You could have done this much much easier. Instead of calculating the top property for the container you can set its scrollTop property, and you guess what - you don't have to check if the content moves upper than 0 or lower than height because scrollTop property can not be set to a value smaller than 0 or greater than container's height!

Here's your modified fiddle

Notice that I had to wrap everything with additional <div id="everything">...</div> so the scrollbar won't be scrolled together with the #scroll-area div.

Also I assume using clientHeight instead of offsetHeight for .scroll-content div to include padding in the cntHeight variable.

More info on the scrollTop property you can find in this article.

2
  • I'v already tried to use the scrollTop before, but it didn't work for hidden overflow. Not sure how you can do this with hidden overflow. But now you've solved the problem. Thanks. Commented Apr 9, 2013 at 11:22
  • I think the easiest way to understand this is to prepare a box with overflow:scroll and examine its behaviour. When you do so, you'll notice that you get the native scrollbar. When you scroll the content, its scrollTop property changes. My jsfiddle solution is exactly opposite - we modify scrollTop property to scroll the content. What overflow:hidden does, is only hiding native scrollbar.
    – matewka
    Commented Apr 10, 2013 at 12:38

Not the answer you're looking for? Browse other questions tagged or ask your own question.