Need some help?

I'm usually available for small jobs or problem solving with jQuery or css. Just get in touch.

Buy me a drink

If you've found this useful, particularly for commercial projects, you might consider making a small donation.

Vertical scrollbar using jQuery UI slider

Now (finally, been meaning to do this for about a year…) also available as a jQuery plugin.

Wasted another morning messing about with the jQuery UI slider, trying to get it to work vertically rather than horizontally. Seems like quite a few others have been looking for the same thing, so here’s my attempt. I began by adapting the code on the jQuery UI site for a horizontal slider. This worked, but seemed unnecessarily complex, so I had another go, starting from the vertical slider code. The result is a lot cleaner.

The code assumes a single div with fixed height (#scroll-pane in my example) which contains an absolutely positioned div (#scroll-content) which contains the content for scrolling. I’ve positioned the scrollbar immediately to the right of #scroll-pane, but it can go anywhere you like. There’s a bit of calculation involved, and then the top value of #scroll-content is changed via the slider to make the content scroll up and down.

There’s a fundamental aspect of the way the vertical slider works which took me a little time to get my head round, and that’s that the slider as a default starts from zero at the bottom and increases upwards – which is the wrong way round for a vertical scroller, hence the need for a bit of extra calculation.

Here’s the css:

#scroll-pane { float:left;overflow: auto; width: 420px; height:300px;position:relative;border:1px solid gray;margin-left:50px;margin-bottom:25px;display:inline}
#scroll-content {position:absolute;top:0;left:0}
.scroll-content-item {background-color:#fcfcfc;color:#003366;width:100px;height:100px;float:left;margin:10px;font-size:3em;line-height:96px;text-align:center;border:1px solid gray;display:inline;}
#slider-wrap{float:left;background-color:lightgrey;width:20px;border:1px solid gray;border-left:none;}
#slider-vertical{position:relative;height:100%}
.ui-slider-handle{width:20px;height:10px;margin:0 auto;background-color:darkgray;display:block;position:absolute}

and here’s the javascript:

$(function() {
//change the main div to overflow-hidden as we can use the slider now
$('#scroll-pane').css('overflow','hidden');

//compare the height of the scroll content to the scroll pane to see if we need a scrollbar
var difference = $('#scroll-content').height()-$('#scroll-pane').height();//eg it's 200px longer 

if(difference>0)//if the scrollbar is needed, set it up...
{
   var proportion = difference / $('#scroll-content').height();//eg 200px/500px
   var handleHeight = Math.round((1-proportion)*$('#scroll-pane').height());//set the proportional height - round it to make sure everything adds up correctly later on
   handleHeight -= handleHeight%2; 

   $("#scroll-pane").after('<\div id="slider-wrap"><\div id="slider-vertical"><\/div><\/div>');//append the necessary divs so they're only there if needed
   $("#slider-wrap").height($("#scroll-pane").height());//set the height of the slider bar to that of the scroll pane


   //set up the slider 
   $('#slider-vertical').slider({
      orientation: 'vertical',
      min: 0,
      max: 100,
      value: 100,
      slide: function(event, ui) {//used so the content scrolls when the slider is dragged
         var topValue = -((100-ui.value)*difference/100);
         $('#scroll-content').css({top:topValue});//move the top up (negative value) by the percentage the slider has been moved times the difference in height
      },
      change: function(event, ui) {//used so the content scrolls when the slider is changed by a click outside the handle or by the mousewheel
         var topValue = -((100-ui.value)*difference/100);
         $('#scroll-content').css({top:topValue});//move the top up (negative value) by the percentage the slider has been moved times the difference in height
      }
   });

   //set the handle height and bottom margin so the middle of the handle is in line with the slider
   $(".ui-slider-handle").css({height:handleHeight,'margin-bottom':-0.5*handleHeight});
	
   var origSliderHeight = $("#slider-vertical").height();//read the original slider height
   var sliderHeight = origSliderHeight - handleHeight ;//the height through which the handle can move needs to be the original height minus the handle height
   var sliderMargin =  (origSliderHeight - sliderHeight)*0.5;//so the slider needs to have both top and bottom margins equal to half the difference
   $(".ui-slider").css({height:sliderHeight,'margin-top':sliderMargin});//set the slider height and margins
   
}//end if

//code to handle clicks outside the slider handle
$(".ui-slider").click(function(event){//stop any clicks on the slider propagating through to the code below
   	event.stopPropagation();
   });
   
$("#slider-wrap").click(function(event){//clicks on the wrap outside the slider range
	  var offsetTop = $(this).offset().top;//read the offset of the scroll pane
	  var clickValue = (event.pageY-offsetTop)*100/$(this).height();//find the click point, subtract the offset, and calculate percentage of the slider clicked
	  $("#slider-vertical").slider("value", 100-clickValue);//set the new value of the slider
}); 
	 
//additional code for mousewheel
$("#scroll-pane,#slider-wrap").mousewheel(function(event, delta){
	var speed = 5;
	var sliderVal = $("#slider-vertical").slider("value");//read current value of the slider
	
	sliderVal += (delta*speed);//increment the current value

	$("#slider-vertical").slider("value", sliderVal);//and set the new value of the slider
	
	event.preventDefault();//stop any default behaviour
});

});

Here’s a demo page. I imagine most people want to use this with their own styling, so I’ve used some pretty minimal styling which is easily adaptable.

I’ve tested this in IE6, IE7, IE8, FF3.6, Safari 4, Chrome and Opera9/10/11 on Win/XP, FF7 and Chromium on Ubuntu, and Safari 5 on Mac OS X/Snow Leopard.

Feel free to reuse the code or adapt for your own purposes. If you use it for a commercial website you might consider making a donation via the link under the menu on the left. I’d welcome any comments or suggestions for improvement below.

Please don’t link directly to the javascript on my site. Due to the number of hits on my bandwidth because people were doing this I’ve had to deny direct access to javascript files. Use a CDN like Google’s instead.

Variations on the basic slider

24 August 2011 – auto scroll on load

Here’s a variant which scrolls automatically when the page loads – in response to this comment, I’ve put together a variant which includes separate buttons for scrolling. Demo here.

3 August 2011 – buttons for scrolling

In response to this comment, I’ve put together a variant which includes separate buttons for scrolling. Demo here.

Updated Updated 28 October. Dick points out that if you try and drag the scrolling buttons it can occasionally cause the scroller to break. I can’t recreate this at all, but have added some code to prevent the buttons being dragged, which Dick confirms fixes the problem.

10 July 2011 – scrolling to anchors

Here’s another variant that additionally allows scrolling to anchors. This assumes markup where the anchors are assigned a class which is also added to the ‘target’ scroll point within the div. View source for the details.

Then all it needs is:

$('#anchors a').click(function(){

	var difference = $('#scroll-content').height()-$('#scroll-pane').height();//calculate the difference - not needed if within the main slider code
	
	var targetclass = ($(this).attr('class'));//read the class of the clicked anchor
    
	var position = $("#scroll-content ."+targetclass).position();//search for a div with matching class and read its position
    var topValue = -(position.top);//content top is just the negative of the top position
		
	if (topValue>0) topValue = 0;//stop the content scrolling down too much
	if (Math.abs(topValue)>difference) topValue = (-1)*difference;//stop the content scrolling up too much

	sliderVal = (100+(topValue*100/difference));//calculate the slider position from the content position
	$("#slider-vertical").slider("value", sliderVal);//set the slider position

	return false;

});

29 May 2011 – slider on a div that’s initially hidden

I’ve had a couple of comments recently asking why the slider doesn’t work when the div is hidden on page load and only visible after a click. This happens because when the div is hidden (via display:none), most browsers read it as having zero height, and hence all the calculations say no scrollbar is required.

The solution to this is to run the slider code as a function, and call this when the hidden div is displayed, by attaching the function to whatever event displays the div. This is a straightforward adaptation of the code to cope with the div being resized, below. There’s a demo here, view the code to see how it works.

13 April 2011 – slider with percentage height that resizes with window

In response to Igor’s comment, a variant on the “resize content” scrollbar that also supports a percentage height .scroll-pane and resizes with the viewport resize. I’ve simply added an event to call the setSlider function on a window resize, and tweaked the code to always reinstate the scrollbar (if needed). Demo here

23 January 2011 – adding easing

Had a couple of comments asking about easing lately. It doesn’t work well with the code as it is, because the bar scrolls at every mouse move. However, if the slider code is changed to call the animation on the change event instead of the slide event, then it is possible, although the scrolled content will not move until the slider is stopped.

   //set up the slider 
   $(this).find('.slider-vertical').slider({
      orientation: 'vertical',
      range: 'max',
      min: 0,
      max: 100,
      value: 100,
      change: function(event, ui) {
         var topValue = -((100-ui.value)*difference/100);
         $(this).parents('.scroll-pane').find('.scroll-content').animate({top:topValue},1000,'easeOutBounce');//move the top up (negative value) by the percentage the slider has been moved times the difference in height
      }
   });

Here’s a demo. Personally, I don’t care for it…but each to their own.

14 January 2011 – adding jQuery UI draggable/droppable to make a shopping cart

In response to Juan’s comment, here’s another extension to the basic slider to allow dragging from the scrolling div and dropping into a basket. Minimal droppable code added but it gives the basic idea.

13 January 2011 – resizing the scroll content after load

In response to this comment, here’s yet another demo which copes with additional content being added to the scrolled div after it’s been set up. I’ve done this by functionalising the code that sizes and sets the slider, and calling this function when new content is added (for example by an ajax call).

This adds a little extra complexity because if the scroll-pane is resized after the scrollbar has been moved, then this needs repositioning as well:

var contentposition = $scrollpane.find('.scroll-content').position();//read the position of the scrolled div...	
var newSliderValue = 100*(1-Math.abs(contentposition.top)/difference);//...and calculate the slider position from it
$scrollpane.next().find(".slider-vertical").slider("value", newSliderValue);//then set the new value of the slider

This code is adapted from the code for multiple scrolling divs below. View the source on the demo to see the full code.Modified 27 February 2011 in line with modifications to multiple slider code. Updated 11 April 2011 to remove the slider if it is no longer needed after a resize. Amended 7 November 2011 to correctly position the scrolled div after a resize.

8 January 2011 – multiple scrollbars on one page

After these two questions within days of each other, I’ve amended the code so that multiple scrolling elements are supported:

$(function() {
$('.scroll-pane').each(function(){
//change the main div to overflow-hidden as we can use the slider now
$(this).css('overflow','hidden');

//wrap an extra div around the scrollpane so we can use the mousewheel later
$(this).wrap('<\div class="scroll-container">');

//compare the height of the scroll content to the scroll pane to see if we need a scrollbar
var difference = $(this).find('.scroll-content').height()-$(this).height();//eg it's 200px longer 

if(difference>0)//if the scrollbar is needed, set it up...
{
   var proportion = difference / $(this).find('.scroll-content').height();//eg 200px/500px

   var handleHeight = Math.round((1-proportion)*$(this).height());//set the proportional height - round it to make sure everything adds up correctly later on
   handleHeight -= handleHeight%2; 

   $(this).after('<\div class="slider-wrap"><\div class="slider-vertical"><\/div><\/div>');//append the necessary divs so they're only there if needed
   $(this).next('.slider-wrap').height($(this).height());//set the height of the slider bar to that of the scroll pane


   //set up the slider 
   $(this).next().find('.slider-vertical').slider({
      orientation: 'vertical',
      min: 0,
      max: 100,
      value: 100,
      slide: function(event, ui) {
         var topValue = -((100-ui.value)*difference/100);
         $(this).parent().prev('.scroll-pane').find('.scroll-content').css({top:topValue});//move the top up (negative value) by the percentage the slider has been moved times the difference in height
      },
      change: function(event, ui) {
         var topValue = -((100-ui.value)*difference/100);
         $(this).parent().prev('.scroll-pane').find('.scroll-content').css({top:topValue});//move the top up (negative value) by the percentage the slider has been moved times the difference in height
      }
   });

   //set the handle height and bottom margin so the middle of the handle is in line with the slider
   $(this).next().find(".ui-slider-handle").css({height:handleHeight,'margin-bottom':-0.5*handleHeight});
   var origSliderHeight = $(this).next().find(".slider-vertical").height();//read the original slider height
   var sliderHeight = origSliderHeight - handleHeight ;//the height through which the handle can move needs to be the original height minus the handle height
   var sliderMargin =  (origSliderHeight - sliderHeight)*0.5;//so the slider needs to have both top and bottom margins equal to half the difference
   $(this).next().find(".ui-slider").css({height:sliderHeight,'margin-top':sliderMargin});//set the slider height and margins


}//end if
	
	//code for clicks on the scrollbar outside the slider
	$(".ui-slider").click(function(event){//stop any clicks on the slider propagating through to the code below
   		event.stopPropagation();
   	});
   
	$(".slider-wrap").click(function(event){//clicks on the wrap outside the slider range
	  	var offsetTop = $(this).offset().top;//read the offset of the scroll pane
	  	var clickValue = (event.pageY-offsetTop)*100/$(this).height();//find the click point, subtract the offset, and calculate percentage of the slider clicked
	  	$(this).find(".slider-vertical").slider("value", 100-clickValue);//set the new value of the slider
	}); 
	 
	//additional code for mousewheel
	$(this).parent().mousewheel(function(event, delta){
  		var speed = 15;
	    var sliderVal = $(this).find(".slider-vertical").slider("value");//read current value of the slider
		
	    sliderVal += (delta*speed);//increment the current value
 
	    $(this).find(".slider-vertical").slider("value", sliderVal);//and set the new value of the slider
		
	    event.preventDefault();//stop any default behaviour
 	});
	
	
});//end each
	
});


Essentially the changes from the basic script involve changing the ids to classes, and the introduction of a little additional jQuery to traverse to the elements no longer uniquely identified by ids. Here’s a demo. I’ve also each scrolling div in another div to simplify the mousewheel integration. This code modified 27 February 2011 to fix issues with Opera 11.

26 November 2010 – using an image for the slider handle

Following a question about using an image for the slider handle I’ve added an additional demo here which adds some images to the handle.

In order to make this example bulletproof, I’ve used four images (!) – one each for the top and bottom of the handle, one for the white ‘grip’ in the middle, and one for the rest. Although this feels a bit over the top it works for a scrollbar of any length. In order to do this I’ve appended three images into the scrollbar handle html after instantiating the slider:

$(".ui-slider-handle").append('<img id="scrollbar-top" src="scrollbar-handle-top.png"/>');
$(".ui-slider-handle").append('<img id="scrollbar-bottom" src="scrollbar-handle-bottom.png"/>');
$(".ui-slider-handle").append('<img id="scrollbar-grip" src="scrollbar-handle-grip.png"/>');

I’m then using a little bit of additional css:

.ui-slider-handle{background:transparent url(scrollbar-handle-middle.png) repeat-y top left;
#scrollbar-top{position:absolute;top:0;}
#scrollbar-bottom{position:absolute;bottom:0;}
#scrollbar-grip{position:absolute;top:50%;margin-top:-6px;}

So, my repeated image is used as the background image for the slider handle, and the top, bottom and grip are positioned absolutely within the handle.

24 November 2010 – autohide the scrollbar

Robert asked about an autohide function. I really don’t like it, but here’s a demo if you must…

4 October 2010 – additional scrollbar styling example

In response to this question I’ve made another demo with some minor changes to the scrollbar styling and an additional line of jQuery to allow one side of the scrollbar to extend – view source to see the code. Easier to view than describe…IE6 does odd things during the scroll though, which I can’t fix, suggestions welcome.

10 August 2010 – additional autocomplete add on

In response to Dan’s comment below, I’ve added jQuery UI Autocomplete integration here.

Changelog

10 January 2012 – tweaks to mousewheel code

I’ve amended the mousewheel code in three examples where the slider set up may be called more than once, as previously repeated calling of the code resulted in very fast mousewheel scrolling. Examples affected are Add Content, Window Resize and Hidden Divs.

9 November 2011 – packaged as a plugin

Finally packaged this up as a plugin.

1 March 2011 – improved handling of clicks outside handle and mousewheel

In the process of sorting out the Opera issues below, I’ve made a couple of improvements. Previously, clicks beyond the handle, and beyond the actual slider (which is less high than #slider-wrap to accommodate the handle) weren’t handled very well, and didn’t work in IE. They do now, by looking at the point at which the click was made and moving the slider appropriately. This replaces the changes made 16 January 2011. I’ve also simplified the mousewheel code to move #scroll-content from the slider by using the change option – see the code above, which replaces original code added 4 August 2010. These changes are now applied to all the demos.

27 February 2011 – amendments for Opera 11 issues

Following a contact from a user reporting difficulties with Opera 11 when resizing the scroll content, I have amended the demos for both this and for the multiple slider. Opera 11 doesn’t like the scrollbar being absolutely positioned, it seems, so all demos are now updated to position the scrollbar differently. This doesn’t significantly affect the javascript. This wasn’t an issue with Opera 9 or Opera 10. Makes a change from IE messing things up I suppose…

16 January 2011 – handle clicks at top and bottom of the scrollbar correctly

Ohm-ish points out that clicks on the top and bottom of the scrollbar, outside the handle, do not result in a scroll. This is because the slider range is restricted to less than the total height of the scrollbar to allow the handle to fit in.

Attempts to use the whole height of the slider work, but then the scrollbar handles doesn’t track the mouse correctly. Experimentation shows that adding .ui-slider-range sorts clicks above the slider range – this needs the following css:

.ui-slider-range{position:absolute;width:100%}

and I’ve then added a little jQuery to cope with clicks below the slider range:

//position the slider range div at the top of the slider wrap - this ensures clicks above the area through which the handle moves are OK
$(".ui-slider-range").css({top:-sliderMargin});

//add a click function to ensure clicks below the area through which the handle moves are OK
$("#slider-wrap").click(function(){//this means the bottom of the slider beyond the slider range is clicked, so move the slider right down
   $("#slider-vertical").slider("value", 0);
   $('#scroll-content').css({top:-difference});   
})

This has now been added to all the demos and the code shown above.

15 November 2010 – ensure the handle height margins are correct

Thanks to Thom for a suggested addition to ensure the handle height is exactly divisible by two. Without this, browsers other than FF show a 1px gap under the slider handle when it’s at the bottom of the slide.

8 November 2010 – allow for the scrollbar not being required

Following Jorge’s question below, I’ve amended the code slightly so that the slider is only added if it’s needed (if the height of #scroll-content is greater than the height of #scroll-pane), and as part of this added the necessary html for the scroller via jQuery. I’ve also added a line so the height of the scrollbar is set to the height of #scroll-pane.

8 September 2010 – mouse and scrollbar synced correctly

Following Rob’s comment (#5 below) I’ve amended both the css and javascript to fix a problem where the mouse and scrollbar weren’t in sync. Both the code on this page and the demo are updated.

4 August 2010 – mousewheel integration

Following Yves’ comment below I thought I’d have a go with adding mousewheel functionality as well. I used Brandon Aaron’s mousewheel plugin.

Then I’ve added the following additional javascript:

$("document").mousewheel(function(event, delta){

     var speed = 5;//set the speed of the scroll
     var sliderVal = $("#slider-vertical").slider("value");//read current value of the slider
		
     sliderVal += (delta*speed);//increment the current value
 
     $("#slider-vertical").slider("value", sliderVal);//and set the new value of the slider
		
     var topValue = -((100-sliderVal)*difference/100);//calculate the content top from the slider position
		
     if (topValue>0) topValue = 0;//stop the content scrolling down too much
     if (Math.abs(topValue)>difference) topValue = (-1)*difference;//stop the content scrolling up too much
		
     $("#scroll-content").css({top:topValue});//move the content to the new position

     event.preventDefault();//stop any default behaviour

});

I’ve kept this code separate from the rest so you can use it as required. It’s included in the demo page. The mousewheel works anywhere on the page on the demo – to restrict it to operate only on the scrolling div itself the opening statement would be amended to:

$("#scroll-pane,#slider-wrap").mousewheel(function(event, delta){...etc

107 responses to “Vertical scrollbar using jQuery UI slider”

  1. Yves says:

    Thanks for the informative article. Mouse-wheel support would certainly be a great addition !

  2. Simon says:

    Thanks. You could try this plugin for the mousewheel.

    EDIT:Mousewheel support is now included on the demo.

  3. Dan says:

    I’ve begun using this to try it out; I was thinking exactly the same… editing the horizontal and the nightmare began ensuing. This is a great solution to an obvious problem, well done.

    I’m intrigued as to whether ‘auto-complete’ type functionality can be factored into this at all? I’ve got a lot of options in my slider (it’s used to navigate through a user’s assets) and quick finding what you want would be a great addition. i.e. moving slider to a position with an event?

    Great to hear your thoughts; and if its just silly.

  4. Simon says:

    Hi Dan

    Interesting suggestion – I’ve added this functionality to the basic slider here.

  5. Rob says:

    Great adaptation! Slight problem though, in that the drag bar does not track the exact location of the mouse. I saw that on the demo page under Chrome and IE 8.

  6. Simon says:

    Rob – you’re right – I’d noticed that myself earlier and never got round to having a look at it. It’s now fixed.

  7. Winter says:

    Being looking for this solution for so long…… I feel like crying now (believe me), thanks!!!!!!!!

  8. Yann says:

    This is well done and interesting, thanks for sharing… I have added a few lines to my version of your code that enables mousewheel only when the mouse is over the element to scroll, or in the actual state your document (your page) will not scroll at all, only your div will.

    I’m pretty sure I’ve done it the wrong way, that’s why I leave you do it better than me. (for example with my code, I cannot have two scrollbars on the same page, but that’s OK for me).

  9. Simon says:

    Thanks. Yes, my demo page works with the mousewheel anywhere on the page – in a real-life situation you would make the mousewheel more specific using something like:

    $("#mydiv").mousewheel(function(event, delta){...etc
  10. Php coder from Goa, India says:

    Hi,
    Is it possible to color scroll bar like this one? http://jqueryui.com/demos/slider/#slider-vertical

    Kind Regards

  11. Simon says:

    Yes, that’s pretty straightforward. I can use the .ui-slider-range element which is created by the javascript. This needs a bit of css:

    .ui-slider-range{background-color:yellow;position:absolute;width:100%}

    and a small addition to the javascript:

    $(".ui-slider-range").css({top:-sliderMargin});

    after the slider height and margins are set. You can see an amended demo here.

  12. Adrian says:

    Hi, this is almost exactly what I’ve been looking for, thank you…

    However the one remaining issue I have is I need the height of the scroll area to be the browser height (minus 200px for the header/footer)

    Any ideas?

  13. Simon says:

    Hi Adrian

    You should be able to do this quite simply by adding the following at the start of the javascript:

    $("#scroll-pane").height($(window).height()-200);//set the scrollpane to the window height - 200px
    $("#slider-wrap").height($("#scroll-pane").height());//set the slider height the same as the scrollpane height
    

    Hope that helps

  14. Jorge says:

    How can I hide the scrollbar when it’s not needed?

  15. Simon says:

    I’ve added this functionality now – by checking if the scrollbar is required, and only adding if it is.

  16. Thom says:

    Hi Simon, thanks for sharing this – however, doing some testing I found the proportion formula to be wrong used to calculate the size of the handle, it should be:

    var proportion = pane.height()/content.height();

    I’ve also tweaked the handle formula a bit ensuring we get whole numbers after multiplying by 0.5:

    var handleHeight = Math.round(proportion*pane.height());
    handleHeight -= handleHeight%2;//Make sure this is divisible by 2 as we're multiplying by 0.5 later on
    
  17. Simon says:

    Thanks for your comment. My proportion calculation is not wrong – you are achieving the same result by a different way by changing both the proportion and handleHeight calculations.

    Your extra line of code ensuring the handleHeight is divisible by two is a good idea and in some cases stops the handle finishing one pixel short. I’ve added this to the code.

  18. Robert says:

    How about auto-hide function?
    If you move mouse out of div region it hides. If you move inside div region it shows on div content (space saving technique).

  19. Simon says:

    Hi Robert

    I’m not quite sure myself whether this makes for a good user experience. However, it’s simply done. I’ve positioned #slider-wrap absolutely within #scroll-pane. This necessitates a change to the css:

    #slider-wrap{position:absolute;top:0;right:0;background-color:lightgrey;width:20px;border-left:1px solid gray;}

    and then using .append instead of .after to insert #slider-wrap:

    $("#scroll-pane").append('<\div id="slider-wrap"><\div id="slider-vertical"><\/div><\/div>');

    and finally adding the show and hide code:

    $("#slider-wrap").hide();//hide the slider after it's set up
    $("#scroll-pane").hover(function(){	$("#slider-wrap").show();},function(){$("#slider-wrap").hide();});//show on hover

    You can see an amended demo here.

  20. Ashish says:

    What about using the scrollable DIVs in two tabs? Sorry, its not working at my end while trying with tabs and both tabs may have scrollable DIV. Please suggest.

  21. Randall says:

    Love this simple approach! I have simplified it even more and made some changes for my use but nothing needs to be changed with your code.

    Now how could we get more than one of these to function properly in a page at a time? I would love to be able to use this that way:D

    Cheers!

  22. Simon says:

    Wow, two requests in the space of a few days asking the same thing! I’ve added this under the variations section, and there’s a demo here.

  23. rstat1 says:

    First thanks for this awesome bit code. It was big help to me on a current project.

    The only issue I’m having is updating the handle size when content is added via AJAX. It’ll still scroll but the slider goes less than a quarter of the way down and stops, refusing to go any further

  24. Simon says:

    See under the variations section for some comments on this, and here for a demo.

  25. Ohm-ish says:

    Hey. Nice work!

    Would it be easy/possible (for me or you) to add some easing using jquery?

  26. Simon says:

    As it stands, I don’t think you could apply easing, as the scrolling is not done via .animate. However, changing this line in the jQuery:

    $('#scroll-content').css({top:topValue});

    to this:

    $('#scroll-content').animate({top:topValue},20)

    Should allow you to use some easing. Having experimented, however, I don’t think it works very well since each individual move of the scrollbar produces only a small animation and hence any easing is not very evident, if at all. Prepared to be corrected on this if anyone has managed it…

    EDIT: OK, corrected myself. The trick is to call the animation from the change event instead of the slide event. Have a look at the example under variations section above.

  27. Ohm-ish says:

    Some minor “bugs”:

    The less content – the more you have to roll the mousewheel to scroll.
    If the content is only 1 textline bigger than the box, I have to roll the wheel many times to see it (seems like a percentage thing).
    Can I somehow adjust the number of lines the scrollwheel scrolls maybe?

    Clicking on the very top and bottom of the scroll pane has no effect (I have to hit below/over the middle of where the scrollbutton would be)

    Hope it makes sense

  28. Simon says:

    Hello again

    If you amend the speed variable on this line:

    var speed = 5;

    then I think that addresses your scroll wheel problem – not something I’ve noticed really. Increasing the speed variable means less mousewheel turns are required. If this still doesn’t do it, then it would be possible to set the variable programatically dependent on the relative size of the scroll pane and the scroll content.

    EDIT: Clicks at the end of the scrollbars should now work OK – see changelog for 16 January, and update 1 March.

  29. Juan Olano says:

    This is just great… thanks!!!! At this point I am thinking that this offers a quick way to locate an item.. How abot dragging / dropping capabilities to another div? similar to the Shopping Cart example in jqueryUI.com, where you can drag an element from a Accordion into a basket. I would love to be able to use this that way…

    Thanks!

  30. Simon says:

    Thanks Juan. I’ve added a simple demo adding draggable/droppable to the basic slider to the variations section, and there’s a demo here.demo here.

  31. I was thinking, I will try to do something like this with some easing on the scroll do you think its possible?

    Thanks for setting this up

  32. Simon says:

    I don’t think the way this works lends itself to using easing – see my reply #26 above.

    EDIT: This is possible with a bit of a tweak – see the example under variations section above.

  33. mamjed says:

    Amazing! I have been looking for something like this for ages. I have one question, how would I have jquery recalculate the amount needed to be scrolled if I had the contents change size?

    Just saw the alternative method, but there is a glitch, upon resizing the scroll speed gets messed up, and fixes?

  34. Simon says:

    Mohsin

    Thanks for your comment. I don’t know what you mean by glitch with scroll speed. If you can give further information I’ll have a look.

  35. Daniel says:

    SImon, thanks this is very close to what I need. Can it be adapted to scroll a tbody while leaving the thead in place?

  36. Simon says:

    Hi Daniel

    Not trivial to adapt for a table I think, because you need two nested elements (#scroll-pane and #scroll-content) to allow the scrolling to work, and the table html construct doesn’t immediately lend itself to this. I haven’t tried this, but an approach might be maybe split thead and tbody into two different tables, then wrap a div around tbody for the scrollng.

  37. Brent says:

    Hi,

    Thanks for this. I made a small change that might help others in the future.

    I didn’t want the height of the scroll bar to be as long as #scroll-pane, ie: the scroll bar proportions needed calculating based on the height of #slider-wrap, not #scroll-pane. My change also meant I could lose a line of JS and replace it with a single CSS rule.

    What I did in detail:

    Replaced this:

    var handleHeight = Math.round((1-proportion)*$('#scroll-pane').height());//set the proportional height - round it to make sure everything adds up correctly later on
       handleHeight -= handleHeight%2; //ensure the handle height is exactly divisible by two
    
       $("#scroll-pane").after('');//append the necessary divs so they're only there if needed
       $("#slider-wrap").height($("#scroll-pane").height());//set the height of the slider bar to that of the scroll pane

    With this:

    $("#scroll-pane").after('');//append the necessary divs so they're only there if needed
       var handleHeight = Math.round((1-proportion)*$('#slider-wrap').height());//set the proportional height - round it to make sure everything adds up correctly later on
       handleHeight -= handleHeight%2; //ensure the handle height is exactly divisible by two

    … and then gave #slider-wrap a height in CSS.

  38. Simon says:

    Hi Brent

    Thanks – I think in fact I originally had it set up as you describe, but added the height setting into the javascript just to make it more portable.

  39. Ohmish says:

    Hey Simon

    Do you know an easy way to scroll down to the bottom of the text in your scrollbar?
    Something like
    $(‘#somebutton’).click(function() {
    // scroll down to bottom code
    });

  40. Ohmish says:

    Hi again
    I fiddled a bit with it, and found out that I could just use this to scroll down:
    $(“#slider-vertical”).slider(“value”, 0);
    $(‘#scroll-content’).css({top:-difference});

  41. lorife says:

    Hi,
    your component is great..but i have a problem when using jquery Ui theme.

    try using your main demo with the standard theme Ui-lightness and you’ll see that the scrollbar is the wrong size..

    please can you fix it?

  42. Simon says:

    Hi Lorife

    I’ve not built this with the theme in mind, so it doesn’t surprise me that it’s not quite right – in fact the handle moves correctly, but the background to the scrollbar isn’t long enough as you say. I added the #slider-wrap element to cope with this and make it more flexible. However, you can combine the demo with a coloured background and the demo with an image for the handle to create pretty much any styling you want.

  43. Mitch Malone says:

    Simon,

    I have partially rewritten this function as a plugin that can be recycled and reused throughout a page. I just thought I’d drop you a note and ask if you mind if I release this plugin on Github, with obvious credit to your original work?

    You can see my code here: http://jsfiddle.net/mitchmalone/XRnxL/

    Kind regards,

    Mitch Malone

  44. Simon says:

    Hi Mitch

    Thanks for asking, that’s fine.

    Simon

  45. george says:

    Thanks so much for this Simon. It’s been a big help.

  46. Brandon says:

    Very, very good.

  47. Mike says:

    Great tool. I am using the Ajax version…. there is an issue with the resizing of scroll. The resizing works fine, but fail to hide the scrollbar if it is not required once added already. I think your scripts only appends to the existing scroll but it doesn’t reset the scroll. Is there any way to reset the scroll (ajax version with dynamic content)?

    Regards,
    Mike

  48. Simon says:

    Mike

    Thanks. You’re right, I wasn’t catering for the scrollbar not being required after a resize. I’ve added this to the demo now.

  49. Igor says:

    Hi,

    Great tool, I’ve been playing around a little bit, I had following question/comment:
    Let’s say #scroll-pane is set with a height: 550px, the scroll-content is not much, the scrollbar is not shown…
    After resizing the browserwindow [IE, FF, Opera, ...] to a height, let’s say 220px, the scrollbar remains invisible…

    Also, how about a height: 100% instead of a fixed height…

    Kind regards,
    – Igor

  50. Simon says:

    Hi Igor

    Thanks, I’ve added another variation above to cope with a percentage height .scroll-pane and window resize. I think however, for a fixed height .scroll-pane I wouldn’t expect a window resize to invoke or remove a scrollbar.

  51. Alan says:

    Hi, great bit of code. What would be the best way of adding little arrows heads at the top and bottom of the scroll bar. ?

    Thanks

  52. Simon says:

    Alan, if you have a look under “Variations – 26 November 2010 – Using an image for the slider handle” on my page then you’ll see an explanation of how I used images on the scrollbar handle.
    There’s an example page here.

    The example code allows for a separate top and bottom image which would work for your arrows.

  53. hes says:

    Thanks, man!!! I found one bug with the latest version of jquery. When you drag the slider, sometimes you drag the url instead. Strange. With older version you used is everything ok.

  54. eleni says:

    I use the code from the demo -page.Really helpfull after spending hours on looking for a slider -verical!!Thanks!!!!!

  55. Thanks for the plugin. I have a gallery that I wanted to be able to scroll larger the large image that’s replaced by thumbnails.

    Long story short the scrollbars were stacking because your code uses “.after()” which will start to stack. I created a div to contain the scroll bar and then used .html() instead so it automatically replaces. That made a little more sense to me personally.

  56. Simon says:

    Hi Ethan

    In some of the other examples above I’ve catered for this by checking if the scrollbar exists – but your solution would work equally well – nice idea.

  57. Johnny says:

    Hi,

    Nice scroller. Do it supports scrolling using anchors?

    regards, Johnny

  58. Simon says:

    I’ve added a new variant to support scrolling via anchors.

  59. Gavin says:

    Hi Simon

    Thanks for sharing your knowledge! I have used both the standard version of your scrollbar as well as the one using an image for the grip.

    I noticed today that with both versions the grip does not work in I.E.9 I know you do not support your work but was wondering whether you know of any possible reason?

    Thanks again …

    Gavin

  60. Simon says:

    Problem was that the version of jQuery UI the pages were using breaks in IE9. Good old IE…..
    I’ve updated the version and it seems fine in IE9 now.

  61. Gavin says:

    You are an absolute scholar and a gentleman! Thanks so much, not only for your prompt response, but also for taking the time and care to resolve the issue.

    Yes, I spend more time getting IE6,7, 8 and 9 to behave themselves than on the rest of our project tasks put together … well, almost ;-)

    Silly question though, where do we get the new version of the jQuery UI from?

  62. rajunix says:

    Thank u so much for using UI for scrollbar. But I am using multiple boxes using same code(divs, ids) but it not working. It is useful to work only one scrollbar in the whole page.. I need multiple….. thanku

  63. Simon says:

    There’s an example for multiple scrollers on a page under the variants section. Demo here.

  64. Dave says:

    Really excellent code. Any easy way to make it scroll in increments?

  65. Simon says:

    Dave

    jQuery UI slider supports this via the ‘step’ option. To use this you need to add the parameter to the javascript:

    $('#slider-vertical').slider({
          orientation: 'vertical',
          step: 10,
          min: 0,
          max: 100,.....
          
  66. danny says:

    First, let me thank you for your code. Thanks to it’s discovery, a nervous breakdown was narrowly averted.

    Is there is a way to add arrow buttons at the bottom? Just as an additional option for the user. So they could control the scroll bar by actually clicking on it, using the mouse/track pad, or using the arrow buttons.

    Any ideas would be greatly appreciated…and the ones presented are already a life-saver!

  67. Simon says:

    I’ve added example under variants – here’s the demo.

  68. dennis says:

    is it somehow possible to set the height of the scroll-pane to 100% so it changes size when resizing the browserwindow?

  69. Simon says:

    Dennis

    Yes – there’s an example under variants – here’s the demo.

  70. Vlad says:

    Hi. Is there a way to put an image for the scroll handler so that it streches only in the middle and has its top and bottom rounded, for example? Something like having 3 containers on top of eachother and only the middle one repeats the background.

  71. Simon says:

    Vlad

    Yes – there’s an example under variants – here’s the demo. That uses multiple images in just the way you describe.

  72. jay says:

    Simon,

    Thanks for the “multiple scrollbars on one page” demo. I was at the jQuery UI page, http://jqueryui.com/demos/slider/#side-scroll, and have been looking for horizontal multiple scrollbars for a long time until I found your page.

    I simply need to have multiple horizontal scrollbars on the page using exactly the jQuery UI css and js shown at above URL without having too much code modification. Can you shed some light?

    Thanks.

    Jay

  73. Simon says:

    The approach to take will be very similar to that I’ve employed for my multiple sliders. You would need to wrap all the code that sets the slider up (essentially everything that’s not already in a function) into a new function, and then call this function for each slider using .each() – making sure that. The code is already set up using classes so you shouldn’t need to change the html or css much, if at all.

    Jay – I replied by email to your subsequent comment but apparently your spam filter means I need to complete a form to allow me the privilege of sending you an email. Not welcoming when I’m trying to help you. Perhaps you can unspam and read it.

  74. Jenya says:

    Hello,

    Is it possible to animate the scroll bar? I want it to start moving down automatically once the page is loaded. And stoped once i click on scroller.

    Thank you in advance!

  75. Simon says:

    Added as a variant: auto scroll on load Demo

  76. Josh says:

    Simon, have you seen the new scrollbars used in safari? I modified the css slightly and was able to get this same feel using the auto hide solution. Now I just need to add fading animation to the hide. A good example would be the new scrollbar in Facebook for your online friends. Doesn’t show until you rollover, then fades in when rollover and fade out when rollout. Pretty spiffy!

  77. Simon Suh says:

    thanks for the blog post, i’m reading over your css so I can learn how to customize the appearnce of my own scrollbar based off the jquery UI. Keep up the good work!

  78. Chetaru says:

    Hi..
    Thanks for sharing this information and resources it’s really help full for me with the help of this we can improve our designs and development I really inspire with this information thanks

  79. I just have to say, I’m very impressed with the example code, and your responsiveness to the comments you’ve received from your readers.

    Its great to see when a developer not only posts an awesome solution, but also follows-up and addresses some of the challenges that readers have when implementing your code!

  80. mary says:

    Hi,
    This article is really helpful. How can i add both horizontal and vertical slider in the same page.
    Am using http://jqueryui.com/demos/slider/#side-scroll for horizontal scroll, and ur code for vertical scroll bar. Can u please advice how to resolve the conflict when adding both horizontal and vertical slider in same page.Thanks in advance

  81. Simon says:

    You need to make sure your vertical and horizontal scrollers are identified with separate ids or classes and that the slider is called and set up separately. If you do this there shouldn’t be a conflict.

  82. Varun says:

    how can I remove scrollbar to appear while using anchors to scroll?

  83. Simon says:

    Not very clear what you’re trying to do – if you don’t want the scroller to appear at all you could just hide it with css – but in this case I think it would be easier to dispense with the scrollbar altogether.

  84. Varun says:

    thanks Simon for prompt reply. I changed overflow from “auto” to “hidden” in #scroll pane and in worked perfectly.

    However, I was thinking is it possible to use ‘adding easing’ effect with ‘scrolling with anchors’ technique.

  85. Simon says:

    Hi Varun

    You could plug in the code from the easing variant, yes, but again, if you don’t need the scrollbar I’d just use .animate() to move your div.

  86. Joe says:

    I would like to implement the example: autohide the scrollbar with endless/infinite scroller. any suggestions?
    Thanks in advance!

  87. Simon says:

    Joe

    I think this would be rather odd for users – a scrollbar by definition has a stop at the top and a bottom and isn’t endless. What happens when you’ve scrolled to the bottom – does the scrollbar then jump back to the top? If so I’d suggest that is unexpected behaviour for the user.

    On a practical note, the endless slider works by cloning elements before and after the content to give the appearance of an endless scroll – which if combined with a scrollbar will mean the length of the scroll-content will extend – so that would be a challenge to overcome. Overall if you want the endless scrolling effect I would dispense with the scrollbar entirely, and just use .animate() triggered by up and down buttons. This would be both simpler to build and less confusing to the user.

  88. Hello

    the easying not really working smooth specially with mouse wheel and you have to let go the scrollbar to actually fire the scroll event

    Any thoughts?

    Cristian

  89. Simon says:

    Cristian

    The problem is really that these two aren’t designed to work together – if you’re using a mousewheel you want lots of tiny movements to reflect the scroll – which don’t work well with easing.

  90. Varun says:

    Hi:

    I tried adding easying variant with anchors but no luck.

  91. Varun says:

    Is it possible to adjust scrolling speed using anchor variant?

  92. Simon says:

    The anchors option uses the standard slider options to move – you could try using the animate option on UI Slider – which is what the easing demo uses.

  93. Varun says:

    Awesome. Thanks a million!

  94. Gerben says:

    Is it possible to place the scrollbar at the left side of the div?

  95. Simon says:

    Yes. For the basic slider, change this:

     $("#scroll-pane").after('<\div id="slider-wrap"><\div id="slider-vertical"><\/div><\/div>');

    to this:

     $("#scroll-pane").before('<\div id="slider-wrap"><\div id="slider-vertical"><\/div><\/div>');

    and then in the css move margin-left:50px from #scroll-pane to #slider-wrap.

  96. Mikhail says:

    Thank you! very usefull!

  97. Mr. Battersby,
    Thanks so much for this great resource. Related to the demo (w/buttons) at…
    http://www.simonbattersby.com/demos/vertical_scrollbar_demo_14_scroll_buttons.htm
    I see some weirdness occur when a user could possibly drag the button image(s) off of the click point. This seems to clog up the behavior of the scrollbar. Sometimes, the handle on the slider will vibrate like it’s confused. Again, this happens only when I drag the images off of the click destination/link area on the buttons. I’ve reproduced it in IE9 and FF 7.0.1. I really like this solution, but I’m hesitant to implement it because of the slight bug I’ve found. Do you have any ideas as to why this is happening? I’m wondering if I assign the click handlers to a container with a background image rather than just use the image themselves, if this will fix the issue. I really appreciate what you’ve done, just wondering if you’d noticed this or had any ideas. Thanks in advance for reviewing.

  98. Simon says:

    I’ve added a fix to this problem to the demo.

  99. Björn says:

    Thanks a million. Browsed through the web for easily implementable scrollbars, and tried several without success. Yours is working like a charm!

  100. Varun says:

    Just wondering what parameters need to be changed to make your code scroll horizontal.

  101. Simon says:

    Varun

    The starting point for this code was the horizontal scrollbar example on the jQuery UI site – you might want to take a look at that.

  102. Laura says:

    can you please include the html in your example

  103. Simon says:

    Laura

    It’s easiest if you just view the source code on the demo page – Ctrl+U in everything except Internet Explorer where it’s Page > View Source.

  104. kly411 says:

    Thanks to Simon, Mitch, Brent and all subsequent contributors. This is a major find in my book and pleasantly understandable!

Useful? Interesting? Leave me a comment