Creating a Nice Slider With jQuery UI

March 29th, 2008

Sliders have many things going for them as a UI element; they offer the benefit restricting the choice a user has, without taking up the space of a drop down. If you need to ask the user to select a number between a range, you can either do an input box with validation, a drop down select element listing each possibility, or you can do a slider.

One drawback of a slider is the user not knowing what he’s selected as there’s no discrete output. If you are sliding to scale something, you can eyeball something, but wouldn’t it be nice if the slider provided some feedback to the user (”50%”) as the user was fiddling with it? I’m going to show you how to do just that with the jQuery UI library.

Sorry kids, the movie has been deleted somehow as a result of the latest Wordpress update. I’m working with Mediatemple to see a) what on earth happened with their install script to delete everything that’s NOT Wordpress and b) if they can recover anything.

I had a local backup of the demo, thank goodness, so that’s still up. Unfortunately, not the video.

Check out the demo here

The necessary dependencies :

The code I used is as follows :

HTML

<div id='container'>
	<div class="slider_container">
		<div class='small_label'></div>
		<div class='slider_bar'>
			<div id="slider_callout"></div>
			<div id='slider1_handle' class='slider_handle'></div>
		</div>
		<div class='large_label'></div>
	</div>
</div>

CSS

body { background: #284a6e; }
#container { height: 100px; border: 1px solid #284a6e;}
.slider_container { position: relative; margin-top: 50px; height: 40px;}
.small_label { background: url(minus.gif) no-repeat; height: 19px; width: 19px; overflow: hidden; float: left; }
.slider_bar { background: url(bar.gif) no-repeat; height: 19px; width: 260px;  float: left; margin: 0px 5px; position: relative;}
.large_label { background: url(plus.gif) no-repeat; height: 19px; width: 19px; overflow: hidden; float: left; }
.slider_handle { background: url(selector.png) no-repeat; height: 19px; width: 20px; overflow: hidden; position: absolute; top: 1px;}
#slider_callout { background: url(callout.gif) no-repeat; height: 45px; width: 38px; overflow: hidden; position: absolute; top: -50px; margin-left:-10px;  padding: 8px 0px 0px 0px; font-family: "Myriad Pro"; color: #284a6e; font-weight: bold; text-align: center;}

Update: A couple commenters noticed a little outline gremlin in Firefox 3 when using the slider. Just add * :focus { outline:none } to get rid of it. I’m not sure which element the outline is on, so applying it to * can’t hurt ;)

JavaScript

After I recorded the video, it dawned on me that there’s a way to do this that is a bit simpler: by using the ui object passed in by slider, and grabbing the “left” css property of the handle. That way, the callout matches the css handle at all times, with no calculations needed; and you can reserve minValue and maxValue to return values that are useful for your web application.

Thanks to Andrew and John in the comments, I have fixed some bugs with the code. Now you can click on the bar itself and the callout will fire correctly. For this I utilized the “stop” event, checked if the callout was already visible, and displayed it if not.

The code looks like this :


$(function() {
	$('#slider_callout').hide();
	var calloutVisible = false;
	$('.slider_bar').slider({
		handle: '.slider_handle',
		minValue: 0,

		maxValue: 25,
		start: function(e, ui) {
			$('#slider_callout').fadeIn('fast', function() { calloutVisible = true;});
		},
		stop: function(e, ui) {
			if (calloutVisible == false) {
				$('#slider_callout').fadeIn('fast', function() { calloutVisible = true;});
				$('#slider_callout').css('left', ui.handle.css('left')).text(Math.round(ui.value));
			}
			$('#slider_callout').fadeOut('fast', function() { calloutVisible = false; });
		},
		slide: function(e, ui) {
			$('#slider_callout').css('left', ui.handle.css('left')).text(Math.round(ui.value));
		}
	});
});

For reference purposes, here is the code I used in the video :


$(function() {
	$('#slider_callout').hide();
	$('.slider_bar').slider({
		handle: '.slider_handle',
		minValue: 0,
		maxValue: 240,
		start: function(e, ui) {
			$('#slider_callout').fadeIn('fast');
		},
		stop: function(e, ui) {
			$('#slider_callout').fadeOut('fast');
		},
		slide: function(e, ui) {
			$('#slider_callout').css('left', ui.value).text(Math.round(ui.value * (100/240)));
		}
	});
});

Discuss this post

You may want to remove the console.log() statements from your demo (the prevent it from working in browsers that don’t have Firebug – or that have Firebug disabled).

Very cool work, though!

John Resig said this on March 31st, 2008

Ah, good call. I’ll make that update now– oops :)

Buck said this on March 31st, 2008

That’s really nice, but if you click the destination rather than drag the callout appears at the origin which looks a bit weird and is counter-intuitive. Otherwise it’s pretty elegant.

Andrew Ingram said this on March 31st, 2008

Gasp! You are so right. I need to fix that! Maybe when I get off of work today.

I just realized I need to fix the tabindex on my comment system as well, heh.

Buck said this on March 31st, 2008

Andrew – This is fixed, thanks for bringing it to my attention! I’ll post an addendum as soon as I can.

Buck said this on March 31st, 2008

I tried using the above slider demo, In my code it says slider in not a function , any clue

Madan said this on April 2nd, 2008

It doesn’t work in this demo, or you are trying to recreate this yourself?

If you are trying to recreate this yourself, be sure and download the necessary dependencies. I’ve added them to the post for clarification. It’s dependent on ui.slider.js and ui.base.js from the jQuery UI library.

Buck said this on April 2nd, 2008

Thanks Buck for the reply. I am trying to recreate this myself. After including following dependencies ui.mouse.js,query-dimensions.js,ui.slider.js the javascript errors got corrected. Now after including the above code the slider is not visible. Not sure what I am missing

Madan said this on April 4th, 2008

hello,
Buck I got most of it working now but when I try to move the slider, i am getting an error in ui.slider.js(line 161) as below
this.property.0 is null or not an object(. Any ideas

Madan said this on April 6th, 2008

Finally got it working

Madan said this on April 7th, 2008

Great! Is there something I can add to the tutorial to make it a little more clear? Do you have a URL where we can check it out?

Buck said this on April 7th, 2008

can the slider accept values lower than 1, for example minValue: 0.1 maxValue: 0.9

I have tried with no luck.. do you know if there is a solution?

martha said this on April 9th, 2008

awesome tutorial…very useful. thanks!

Anthony said this on April 10th, 2008

I got another question! I need to have a startValue but it displays de callout image.. how can I have the startValue without the image until I click on the selector?

martha said this on April 11th, 2008

Martha – be sure and put style=”display: none;” on the callout image so it does not show up initially. That way, the showing and hiding from thereon out is handled by the start and stop callbacks.

Buck said this on April 11th, 2008

Sorry but I have another doubt, I have a textbox that have de actual value as the slider move, and also I can write on the textbox a value and the slider will move to that position but if I implement the callout the moveTo will not work, and if I omit the tag of the callout it works…. and I need both, the callout and the texbox.. any suggestions?

martha said this on April 14th, 2008

How could I use this to submit a form?

Dag said this on May 11th, 2008

Helpful tutorial, thanks!
The only issue is that you are a little quiet on my macbook’s speakers.

Jim said this on May 16th, 2008

Dag – what do you mean? You want to use this as a value in a form submit, or do you want this to submit the form itself?

Jim – thanks for the heads up. I’ve got a new microphone, so future tutorials will have better sound. I’ll make sure it’s cranked up enough :)

Buck said this on May 16th, 2008

Dag – I use a separate function to process the values, you can do the same to assign the value to a hidden form element if you wish

stop: function(e, ui) {
var slideVal = Math.round(ui.value);
getDistance(miles, slideVal); //function to process the value

you can do the same on slide as well.
hope that helps.

Johan said this on June 1st, 2008

I really love what you have done here. I have hit a snag though, what changes must/can be made to have 2 sliders on the same page and individually writing their separate values to separate hidden fields?

Ian Huet said this on June 18th, 2008

This is a great little slider, and I’m currently working it into one of my projects. I’ve been working in FireFox 3 and there seems to be a 1px mystery dot (almost like a dead pixel). When I select the slider handle I can see this rogue blue pixel on the top left of the containing div. I’ve uploaded a screenshot to help explain what I’m seeing. I’ve checked this in FF 2.0 on XP and I see nothing, so it seems to be unique to FireFox 3.0. I’m not too concerned as the market for 3.0 is non-existent at this point, just thought I would let you know. Thanks again for this great tutorial!

Kevin said this on June 19th, 2008

Ian Huet –

No changes need to be done, other than changing the id of the second slider, and calling the jQuery code twice. That’s it! If you have any problems, let me know.

Kevin –

Thanks for the compliment. I totally see what you’re talking about and it drives me crazy. I’ll throw it out to my twitter followers and see if anyone can help figure out what’s causing that little gremlin.

Be sure and check back and show me your final slider!

Buck said this on June 19th, 2008

Looks similar to the dotted border which appears if an -handle is used. (…why not use an img… ever tried? that’s sooooo cute – that’s a lil … semantic !?)

DolbeGraeb said this on July 3rd, 2008

we can fix it! just put following in your pagestyle.css:
* :focus{outline: 0;}

DolbeGraeb said this on July 4th, 2008

* :focus { outline:none } worked for me.

Thanks Dolbe

Kevin said this on July 9th, 2008

Thanks Dolbe! I’ll modify the original post in a few.

Buck Wilson said this on July 9th, 2008

you’re welcome =)

DolbeGraeb said this on July 21st, 2008

I finally sat down with a free minute and watched this thing – very cool!

Adam Wulf said this on July 25th, 2008

Is there a way to specify a default value for the slider position? Like say 50.

Z said this on August 15th, 2008

Z, all you have to do is this:

startValue: the number that you want to start it at,

by the minValue and maxValue area.

Connor said this on August 15th, 2008

This is a fantastic little slider, im using it on a ratings project which should be live soon so will let you know when its up. I too had issues creating more than one slider (i need like 10+ on one page) but have sorted it out. Great site bro keep up the good work.

Chris said this on August 22nd, 2008

oh’ 1 small thing, and this is really picky but I don’t think I could work out a way to do this myself, ..that is to have the bar ‘fill-in’ a solid colour (ala’ a progress bar) as you slide, ..so maybe the right hand side of the handle is inset as it is by default, but the left hand side fills with a solid colour as you drag accross. Just a thought for an addition, that would coincidentally be reeally nice for what im working on ;) any ideas how I might achieve that?

Chris said this on August 22nd, 2008

Chris – thanks for the props! Happy this has helped you.

The fill bar is a great idea. So great, in fact, that I’ll probably make a tutorial on it this weekend. Shouldn’t take too much effort, I don’t think, though it will require a transparent .png.

Buck said this on August 22nd, 2008

ok sweet! that’s great Buck, will look forward to a tutorial on that =) !

Chris said this on August 25th, 2008

Hi Buck,

Fantastic little script – really enjoying it, many thanks. Just one humble question:

Multiple instances. The second interface calls up the callout box for interface 1. I’ve tried giving the second instance a ’slider_callout2′ ID and changing the corresponding slider_callout IDs in the second declaration of function(), but no joy.

I suspect I’ve missed something embarrassingly simple, but if you have any ideas what it is, I’d be truly appreciative.

Lotsa thanks again for the script. :-)

James Bent said this on September 1st, 2008

Hello,
Great script! Really smooth and intuitive!

Regards,
Niklas

Niklas Bivald said this on September 5th, 2008

Hello,
Great script! thx.

but if we try move slider whith arrow keys have a bag

Anton said this on September 22nd, 2008

Hi,

look good and I would like to use it, but:….

I need only one handle as you have got it. When I move the handle from left to right, I want the bar to have a different color left from the handle than right from the handle.

Is that doable?
Heiko

Heiko Frosch said this on October 2nd, 2008

@James
here is an example how to do it:

$(function() {
$(’#slider_callout’).hide();
var calloutVisible = false;
$(’.slider_bar’).slider({
handle: ‘.slider_handle’,
minValue: 0,

maxValue: 25,
start: function(e, ui) {
$(’#slider_callout’).fadeIn(’fast’, function() { calloutVisible = true;});
},
stop: function(e, ui) {
if (calloutVisible == false) {
$(’#slider_callout’).fadeIn(’fast’, function() { calloutVisible = true;});
$(’#slider_callout’).css(’left’, ui.handle.css(’left’)).text(Math.round(ui.value));
}
$(’#slider_callout’).fadeOut(’fast’, function() { calloutVisible = false; });
},
slide: function(e, ui) {
$(’#slider_callout’).css(’left’, ui.handle.css(’left’)).text(Math.round(ui.value));
}
});
});
$(function() {
$(’#slider_callout_days’).hide();
var calloutVisible = false;
$(’.slider_bar1′).slider({
handle: ‘.slider_handle’,
minValue: 0,

maxValue: 25,
start: function(e, ui) {
$(’#slider_callout_days’).fadeIn(’fast’, function() { calloutVisible = true;});
},
stop: function(e, ui) {
if (calloutVisible == false) {
$(’#slider_callout_days’).fadeIn(’fast’, function() { calloutVisible = true;});
$(’#slider_callout_days’).css(’left’, ui.handle.css(’left’)).text(Math.round(ui.value));
}
$(’#slider_callout_days’).fadeOut(’fast’, function() { calloutVisible = false; });
},
slide: function(e, ui) {
$(’#slider_callout_days’).css(’left’, ui.handle.css(’left’)).text(Math.round(ui.value));
}
});
});

the first instance has a slider_callout ID, so change the ID in the second instance (slider_callout_days, for example). Then, change the slider_bar class (.slider_bar) in a .slider_bar1 for example. Both should work now!

fano said this on October 3rd, 2008

Nice slider!
Using three sliders on the same page, how can I have each of them individually write its value to a text field and then get the total of all three text fields in a box, Any idea?

Mike said this on October 5th, 2008

Mike-

Sure thing. You can either run this action on the slide: event or the stop: event in each .slider({:

slide: function(e, ui) {
//in addition to what’s already in the slide function…
$(’#id_of_text_box_1′).val(Math.round(ui.value));
$(’#id_of_total_text_box’).val($(’#id_of_text_box_1′).val() + $(’#txtbox2′).val() + $(’#txtbox3′).val());
}

Sorry it’s a little tough to put here… does that make sense?

Buck said this on October 5th, 2008

It perfectly makes sense and working fine! Thanx!
But just another question… How can i give the slider text values instead of numbers and add an interval between them?

Mike said this on October 5th, 2008

I just found out that ‘minValue’ and ‘maxValue’ are not supported in jQuery.UI.1.5.2. You should use ‘min’ and ‘max’ respectively to set the values you want. Hope that helps

fano said this on October 6th, 2008

really cool!
How can javascript be used to assign value?

Paul said this on October 9th, 2008

While drag the same handle two times, it will post an error “this.currentHandle is null “, if Placed in a Modal Dialog.

tt said this on October 23rd, 2008

Great control!
I have only one problem: I set: minValue: 72, maxValue=220.
If I slide is beautiful, but if I just click on one point the slider goes crazy… Any ideas?

Thanks

Diego said this on December 5th, 2008

i have the same problem, my slider goes crazy.

peter grube said this on December 26th, 2008

Hi,

Nice Web and Nice tutorial. Thanks for the Source File.

Thanks.
Omair Rais
http://www.omairarts.com

Omair Rais said this on December 31st, 2008

Hi guys! My site is dynamic and needs that the slide_handle goes to a start position, with out be necessary to use the mouse in the slide_handle even the slide_bar. Those values to the slide_handle come dynamicaly from a data base.
I put the parameter ’starValue’ into the $(’.slider_bar’).slider function, but in any way is necessary to use an any mouse event.
Do you know how can I do to make the slide_handle goes to a position when the page is loaded with out use the mouse?
Thanks.

Cesar said this on January 2nd, 2009

Hey, I just wanna say BIG THANKS for this tutorial ;)

Janko said this on January 10th, 2009

First of all thanks for this. Will any one please let me have an example that contains div slider. it would be like image scroller just what i need that i want to display next and previous button on either sides and if there are display of 5 image and i have 10 image than there should be a cycle way that i can go through next next even on the last div i click on next then next should be first. same on the previous button. that is how it seems that it is in a round motion. and yes on next and previous button click it should be slide just one image not a five image bulk.

Jatin Meshiya said this on February 3rd, 2009

Hey, thanks for this tutorial! Really appreciate it.
However, I can’t get the callout to who as the “slide: function(e, ui)” never fires. The demo doesn’t show the callout either. Is that a bug or am I missing something?

RAM said this on February 3rd, 2009

Whoops, who = work. :-)

RAM said this on February 3rd, 2009

I was on jQuery 1.5. jQuery.com needs version information, but hey, shit happens. ;-)
Thanks!

PS Feel free to delete my posts.

RAM said this on February 3rd, 2009

I really can’t set the start-position of the slider. Please someone?

Stefan said this on February 12th, 2009

I believe this is not compatibl with the new jQuery UI (1.6rc6), many properties and methods in the slider had been changed; am I right!?

Luca P. said this on February 26th, 2009

Hello webmaster
I would like to share with you a link to your site
write me here preonrelt@mail.ru

Alexwebmaster said this on March 3rd, 2009

@Luca, that’s right because I’ve been trying this tutorial with 1.6 and it won’t work. Buck can you update the code or screencast to reflect the UI changes with 1.6?

Aubrey said this on March 31st, 2009

I’ve been meaning to do this for awhile now. I’ll see if I can find the time this week. I’ll be posting it on my new blog: buckwilson.me

Thanks for the feedback!

Buck said this on March 31st, 2009