Keep element in view while scrolling using jQuery
I’ve just completed an interesting project; an online application form that calculated a quote dynamically using Javascript as the user specified their choices. The quote details where to be displayed to the right of the form, but the form was longer than the height of the page so scrolling was required. In order to keep the quote price visible at all time I needed a way to make the element container reposition itself to remain in view when the user scrolled up and down on the form.
I actually thought the solution would be a single search away on Google, but I couldn’t believe that there was no quick answer available. A few people had suggested a css version using position:fixed, but due to the structure of my css and the fact that I wanted a smooth scrolling effect on the element the css idea just didn’t cut it.
I knew jQuery was going to produce my answer, but nobody seemed to have anything available to tell me how. I ended up writing my own against the jQuery framework, which actually proved extremely easy. Hopefully if your looking for something similar this will meet your needs. You can view the working demo here. Ok, lets get started.
First thing to do is make sure you have the jQuery library included on your page. This is super easy to do. If you haven’t got it yet download the production file (19kb) from www.jquery.com. Then simply include it on your page using a script include in your head section.
<script src="jquery-1.3.2.min.js" type="text/javascript"></script>
Next up, give the element that will be dynamically repositioned an id so that it can be found in the DOM. This again is super easy.
<div id="scrollingDiv"> <--- notice the id tag
Your content in here
</div>Now that we have the basics done we need to write the code to reposition the element dynamically using JQuery. This is the technical bit, but I’ll try break it down so it’s easy to understand.
We need to listen out for, and handle, the scroll event. Basically every time the user scrolls their browser window it alerts any code that has registered interest in this event that it has just happened. We will reposition the element when this happens, so this is perfect for us! To do this we use JQuery’s event handling support to attach a function to the window’s scroll event.
$(window).scroll(function() {
do stuff here...
});Now that we are being alerted that the scroll event has fired we need to actually do something. The code below does a few things.
- jQuery traverses the DOM and returns the element who’s id is scrollingDiv
- We call JQuery’s animate function on the returned element and tell it to increase the top margin to the size of the top scroll location (I’ve added 30 to the total because I already have a top margin of 30 on the div. You can remove this if you do not have a top margin already on your div). We also set the animation speed to slow. You can set this to fast, or specify a numerical value in milliseconds if you prefer.
$(window).scroll(function(){
$("#scrollingDiv")
.animate({"marginTop": ($(window).scrollTop() + 30) + "px"}, "slow" );
});Because this event can fire many times in a row we need to make sure we stop all previous repositions before progressing with the latest one. Imagine a users scrolls 3-4 times really fast. We want just the last call to be in control of the repositioning. Ensuring that all repositioning is stopped beforehand makes for much faster handling of the event, resulting in smoother animation. We call this BEFORE the code snippet above.
$(window).scroll(function(){
$("#scrollingDiv")
.stop()
.animate({"marginTop": ($(window).scrollTop() + 30) + "px"}, "slow" );
});Our element now scrolls along with the window. There is one area we can still make this a little smoother though. Whenever the scroll event fires jQuery traverses the DOM looking for our element. In order to alleviate this overhead we can simply store the jQuery reference to our element in a variable when the DOM is initialised and reference this instead.
var $scrollingDiv = $("#scrollingDiv");
$(window).scroll(function(){
$scrollingDiv
.stop()
.animate({"marginTop": ($(window).scrollTop() + 30) + "px"}, "slow" );
});That’s all there is to it. You now have an element that scrolls smoothly into position so that it remains in view at all times. I’ve tested the code in IE6, IE7 and Firefox 3, every one of which works a treat. The complete code snippet is included below. Enjoy!
<script type="text/javascript" src="jquery-1.3.2.min.js"></script>
<script>
$().ready(function() {
var $scrollingDiv = $("#scrollingDiv");
$(window).scroll(function(){
$scrollingDiv
.stop()
.animate({"marginTop": ($(window).scrollTop() + 30) + "px"}, "slow" );
});
});
</script>Tagged as html, jQuery + Categorized as HTML & CSS, jQuery
Hi there.
Thanks for sharing your knowledge…. jQuery is Simply awesome.
Regards
Ibrahim
Excellent piece of code, its excellent for my needs, but the div the scrolls is not in view when the page loads, so when you scroll down the div always stays out of view. I’ve attempted to resolve this by activating the scrolling function when a control has focus, but it still jumps out of view. I’m still playing with it but have not resolved it yet. Any suggestions?
hi again, i resolved the issue by setting a negitive value for the margin top of the div. thanks again for this awesome snip.
Hi Donald, glad you got it working
You just saved me a ton of work! I was about to pull out all the javascript stops and probably end up with a solution with many many more lines.
thanks
i was just looking for it.
first of all, thank you for sharing this!
ran into a problem, though:
i was using jquery 1.2.6 and it worked perfectly, after modifying the code to fit my site of course…but after recently upgrading to 1.3.2, the button (image) doesn’t even move anymore…though I see you’re running jquery 1.3.2 in your example with no problem…
i haven’t spent much time on this, but wanted to see if anyone else had the same problem.
Cool piece of code here!!
I would have this scroll feature but the #scrollingDiv may not ran outside his parent. Any idea to fix this?
Thanks already, Bert
This was exellent! Thanks
Thanks for sharing! Exactly what I needed!
Thanks Just what I needed!
Hi!
thnx for sharing you code. Got it working without any problems
Have a question:
I want to achieve the effect of the menu sliding in and out of the screen when starting from the top of the page.
I have added 40 to the scrolltop location and in css top:-200px .
When you enter the page, the menu is not visible ( i.e. outside of the screen).
The moment you start scrolling downwards, the menu scrolls into the screen.
What I want to achieve is this: the menu scrolls into the screen after scrolling the page about 200 px down and when scrolled back to the top of the page, the menu should scroll out of the screen again. This is becuase the site i’m making also has a header menu.
The testsite ( under construction) is http://test.lethal-zone.eu
I know this can be done, have seen it on a website somewhere, but how to do so in jQuery with your script?
Hi William,
thanks for the tip. I’ve been looking for something like this for a while now, but with a slight twist. What I need is to have the element scroll normally, but remain at the top of the page when it is supposed to disappear under the fold. See how the table header row works in this page: http://drupal.org/project/issues/search/drupal?version0=7.x&issue_tags=Usability,%20d7ux
Anyway, I’m just leaving this here in hope someone can chime in with a useful link.
Thanks again.
Works in Chrome 4.0 on Windows 7. Great.
Hi William
I’ve just found your snippet and I am putting it into place for one of our clients now
Many thanks
Darren, UK
Wonderfull, the .stop() make the scrolling div happier than ever!!!