Creating custom scrollbars in minutes

Today we are going to be customizing scrollbars using jQuery and CSS. There are many scrollbar plugins out there, and some are really good. However, I usually like rolling my own (especially since modifying the way they look can be a hastle). I'm the one who creates it, so I know what to touch and where should I need to modify it. For browsers such as Chrome, Maxthon, and Safari who are webkit browsers, you can style your scrollbars via CSS. But for others like Firefox, Opera, and Internet Explorer its not the case. You want to create a consistent look and feel on all of these browsers right? So how do we go about customizing scrollbars for all browsers?

Enter jQuery Draggable

If you go to the jQuery ui website you'll find a lot of demos about their widgets. What I'm interested in at the moment is the draggable. This allows you to move any DOM element around a container. So we can use this draggable capabilty to this scrollbar example by dragging around a <div>. What you should also know is that you can scroll a page or any content that has a scrollbar on your page using jQuery. So we will fuse the two together to create our scrollbars...

Take a look at the following HTML file:

<!DOCTYPE html>
<html>
    <head><title>Custom scrollbars tutorial</title></head>
    <style type="text/css">
        .container {
            height: 200px;
            width: 420px;
            border: 1px solid #aaa;
            position: relative;
        }

        .visible-area {
            height: 200px;
            width: 400px;
            overflow: auto; /* This creates a scrollbar */
            padding-left: 8px;
            padding-right: 8px;
        }
    </style>
<body>
    <div class="container">
        <div class="visible-area">
            <div class="content">
                Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas feugiat consequat diam. Maecenas metus. Vivamus diam purus, cursus a, commodo non, facilisis vitae, nulla. Aenean dictum lacinia tortor. Nunc iaculis, nibh non iaculis aliquam, orci felis euismod neque, sed ornare massa mauris sed velit. Nulla pretium mi et risus. Fusce mi pede, tempor id, cursus ac, ullamcorper nec, enim. Sed tortor. Curabitur molestie. Duis velit augue, condimentum at, ultrices a, luctus ut, orci. Donec pellentesque egestas eros. Integer cursus, augue in cursus faucibus, eros pede bibendum sem, in tempus tellus justo quis ligula. Etiam eget tortor. Vestibulum rutrum, est ut placerat elementum, lectus nisl aliquam velit, tempor aliquam eros nunc nonummy metus. In eros metus, gravida a, gravida sed, lobortis id, turpis. Ut ultrices, ipsum at venenatis fringilla, sem nulla lacinia tellus, eget aliquet turpis mauris non enim. Nam turpis. Suspendisse lacinia. Curabitur ac tortor ut ipsum egestas elementum. Nunc imperdiet gravida mauris.
            </div>
        </div>
    </div>
</body>
</html>

 

The overflow propery that is set to auto creates a scrollbar because the inner <div> has more content than the height of the outer <div>. Take a look of the screenshot below:

overflow-auto

Now we will have to remove that scrollbar and create two <div> elements (one for the track and one for the track bar) as our scrollbar and then use draggable on the track bar so that we can drag it up or down. To hide our scrollbar we are going to change the value of our overflow CSS property from auto to hidden. This is our new css:

.visible-area {
    height: 200px;
    width: 400px;
    overflow: hidden; /* This hides the OS' default scrollbar */
    padding-left: 8px;
    padding-right: 8px;
}

 

Your scrollbar should disappear when you refresh the page now. Now lets define our track and our track bar. This is our modified HTML file that creates our scrollbar:

<!DOCTYPE html>
<html>
    <head><title>Custom scrollbars tutorial</title></head>
    <style type="text/css">
        .container {
            height: 200px;
            width: 420px;
            border: 1px solid #aaa;
            position: relative;
        }

        .visible-area {
            height: 200px;
            width: 400px;
            overflow: auto; /* This creates a scrollbar */
            padding-left: 8px;
            padding-right: 8px;
        }

        /* Scrollbar CSS */
        .scroll-track {
            background: #ddd;
            width: 10px;
            height: 100%;
            position: absolute; /* We need to move this to the right */
            right: 0; /* Sets the scrollbar to the right */
            top: 0;
            z-index: 999 !important; /* Makes it top most */
        }

        .scroll-track .scrollbar {
            background: #777;
            width: 10px; /* fills the width of the track */
        }
    </style>
<body>
    <div class="container">
        <div class="visible-area">
            <div class="content">
                Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas feugiat consequat diam. Maecenas metus. Vivamus diam purus, cursus a, commodo non, facilisis vitae, nulla. Aenean dictum lacinia tortor. Nunc iaculis, nibh non iaculis aliquam, orci felis euismod neque, sed ornare massa mauris sed velit. Nulla pretium mi et risus. Fusce mi pede, tempor id, cursus ac, ullamcorper nec, enim. Sed tortor. Curabitur molestie. Duis velit augue, condimentum at, ultrices a, luctus ut, orci. Donec pellentesque egestas eros. Integer cursus, augue in cursus faucibus, eros pede bibendum sem, in tempus tellus justo quis ligula. Etiam eget tortor. Vestibulum rutrum, est ut placerat elementum, lectus nisl aliquam velit, tempor aliquam eros nunc nonummy metus. In eros metus, gravida a, gravida sed, lobortis id, turpis. Ut ultrices, ipsum at venenatis fringilla, sem nulla lacinia tellus, eget aliquet turpis mauris non enim. Nam turpis. Suspendisse lacinia. Curabitur ac tortor ut ipsum egestas elementum. Nunc imperdiet gravida mauris.
            </div>
        </div>

        <!-- Our scrollbar markup -->
        <div class="scroll-track">
            <div class="scrollbar">&nbsp;</div>
        </div>
    </div>
</body>
</html>

 

This produces the following:

Custom scrollbars

 

Now that the visual part has been taken cared of, it's time to make it functional using jQuery. First we need to include jQuery source script and the jquery.draggable scripts that you can download here. When content is included via ajax onto your page the scrollbar automatically resizes itself by getting smaller and smaller. We need to also replicate this behavior by updating the size of the of the div's that act as our scrolling bar. This is how our jQuery code looks like:

$(function() {
    //Calculate the size of the draggable bar
    var scrollbarHeight = ($('.visible-area').height() / $('.content').height()) * $('.scroll-track').height();
    $('.scrollbar').height(scrollbarHeight);

    $('.scrollbar').draggable({
        axis: 'y',
        containment: 'parent', //The scroll track
        drag: function() {
            var oldTopPosition = parseInt($(this).css('top'));
            var newTopPosition = (oldTopPosition / $('.scroll-track').height()) * $('.content').height();
            $('.visible-area').scrollTop(newTopPosition); //Scroll the content via jquery
        }
    });
});

 

We first calculate the size of the draggable <div> by dividing the visible area with the amount of content we have (in terms of height) to get a ratio of how much of the bar should be on the scroll track, and then multiplied it by the height of the scroll track to determine the height of the bar. We then used our draggable plugin to make that black bar draggable only on the y axis (you can specify both if you want but that wouldn't be a vertical scrollbar now would it?). The containment is the bounds of this draggable element (which, of coarse, is your scroll track), and then we defined a callback method that fires everytime we drag the bar up or down. In this callback method is where the scrolling occurs. We get the how far along we scrolled on our scrollbar into a ratio and multiply it by the content, then we use the scrollTop() jQuery method. Take note that we used this method on the .visible-area and not the .content. This is because the content isn't the div that has the overflow property. Remember when this property is set to hidden it only hides the content and the default OS' scrolling controls. This is what we inteded to do because we are the ones who will be doing the scrolling. This is how our entire HTML file looks like:

<!DOCTYPE html>
<html>
    <head><title>Custom scrollbars tutorial</title></head>
    <style type="text/css">
        .container {
            height: 200px;
            width: 420px;
            border: 1px solid #aaa;
            position: relative;
        }

        .visible-area {
            height: 200px;
            width: 400px;
            overflow: hidden; /* This creates a scrollbar */
            padding-left: 8px;
            padding-right: 8px;
        }

        /* Scrollbar CSS */
        .scroll-track {
            background: #ddd;
            width: 10px;
            height: 100%;
            position: absolute; /* We need to move this to the right */
            right: 0; /* Sets the scrollbar to the right */
            top: 0;
            z-index: 999 !important; /* Makes it top most */
        }

        .scroll-track .scrollbar {
            background: #777;
            width: 10px; /* fills the width of the track */
        }
    </style>
    <script type="text/javascript" src="jquery-1.7.1.min.js"></script>
    <script type="text/javascript" src="jquery-ui-draggable.js"></script>
    <script type="text/javascript">
        $(function() {
            //Calculate the size of the draggable bar
            var scrollbarHeight = ($('.visible-area').height() / $('.content').height()) * $('.scroll-track').height();
            $('.scrollbar').height(scrollbarHeight);

            $('.scrollbar').draggable({
                axis: 'y',
                containment: 'parent', //The scroll track
                drag: function() {
                    var oldTopPosition = parseInt($(this).css('top'));
                    var newTopPosition = (oldTopPosition / $('.scroll-track').height()) * $('.content').height();
                    $('.visible-area').scrollTop(newTopPosition); //Scroll the content via jquery
                }
            });
        });
    </script>
<body>
    <div class="container">
        <div class="visible-area">
            <div class="content">
                Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas feugiat consequat diam. Maecenas metus. Vivamus diam purus, cursus a, commodo non, facilisis vitae, nulla. Aenean dictum lacinia tortor. Nunc iaculis, nibh non iaculis aliquam, orci felis euismod neque, sed ornare massa mauris sed velit. Nulla pretium mi et risus. Fusce mi pede, tempor id, cursus ac, ullamcorper nec, enim. Sed tortor. Curabitur molestie. Duis velit augue, condimentum at, ultrices a, luctus ut, orci. Donec pellentesque egestas eros. Integer cursus, augue in cursus faucibus, eros pede bibendum sem, in tempus tellus justo quis ligula. Etiam eget tortor. Vestibulum rutrum, est ut placerat elementum, lectus nisl aliquam velit, tempor aliquam eros nunc nonummy metus. In eros metus, gravida a, gravida sed, lobortis id, turpis. Ut ultrices, ipsum at venenatis fringilla, sem nulla lacinia tellus, eget aliquet turpis mauris non enim. Nam turpis. Suspendisse lacinia. Curabitur ac tortor ut ipsum egestas elementum. Nunc imperdiet gravida mauris.
            </div>
        </div>

        <!-- Our scrollbar markup -->
        <div class="scroll-track">
            <div class="scrollbar">&nbsp;</div>
        </div>
    </div>
</body>
</html>

 

That's it! We have created a scrollbar in minutes. Its easy to modify the visual aspects of it because you know where to fiddle and you can add more behaviour to it by, say....changing opacity when you hover in and out for example.

Comments