We help IT Professionals succeed at work.

Scroll DIV with viewport

SandmanNet
SandmanNet asked
on
Medium Priority
1,975 Views
Last Modified: 2012-06-27
Ok, so I have a two-column layout that looks something like this:

http://sandman.net/test/move_div.html

And as you can read on that page. I want the blue #side DIV to scroll along on the page WHEN the viewport "hits" it. I.e if I scroll the page 50px nothing will change, the DIV will scroll along with the viewport, but when the browser viewport "hits" it, it will scroll along, to make sure that it's always shown, when I scroll back up it should remain in it's current position.

If you don't understand, follow the instructions to look at the Apple Store, and you should get an idea on what I'd like.

Can this be done in CSS or does it require javascript? Please let me know. If it does equire javascript, please give me tips on how to solve it using jQuery, since that's the framework I'm using.
Comment
Watch Question

CERTIFIED EXPERT

Commented:
I'm not sure how to do this in Jquery but the method I use is as follows:

n.b. the <br>'s are theye for test purposes to make sure there is a scroll bar in the window. These can obviously be removed.

<div id="floatdiv" style="
position:absolute;
width:200px;height:50px;left:0px;top:0px;
padding:16px;background:#FFFFFF;
border:2px solid #2266AA">
!!CONTENT HERE!!
</div> 
 
<script type="text/javascript"><!--
var floatingMenuId = 'floatdiv';
var floatingMenu =
{
targetX: -250,
targetY: 10,
 
hasInner: typeof(window.innerWidth) == 'number',
hasElement: document.documentElement
&& document.documentElement.clientWidth,
 
menu:
document.getElementById
? document.getElementById(floatingMenuId)
: document.all
? document.all[floatingMenuId]
: document.layers[floatingMenuId]
};
 
floatingMenu.move = function ()
{
if (document.layers)
{
floatingMenu.menu.left = floatingMenu.nextX;
floatingMenu.menu.top = floatingMenu.nextY;
}
else
{
floatingMenu.menu.style.left = floatingMenu.nextX + 'px';
floatingMenu.menu.style.top = floatingMenu.nextY + 'px';
}
}
 
floatingMenu.computeShifts = function ()
{
var de = document.documentElement;
 
floatingMenu.shiftX =
floatingMenu.hasInner
? pageXOffset
: floatingMenu.hasElement
? de.scrollLeft
: document.body.scrollLeft;
if (floatingMenu.targetX < 0)
{
if (floatingMenu.hasElement && floatingMenu.hasInner)
{
// Handle Opera 8 problems
floatingMenu.shiftX +=
de.clientWidth > window.innerWidth
? window.innerWidth
: de.clientWidth
}
else
{
floatingMenu.shiftX +=
floatingMenu.hasElement
? de.clientWidth
: floatingMenu.hasInner
? window.innerWidth
: document.body.clientWidth;
}
}
 
floatingMenu.shiftY =
floatingMenu.hasInner
? pageYOffset
: floatingMenu.hasElement
? de.scrollTop
: document.body.scrollTop;
if (floatingMenu.targetY < 0)
{
if (floatingMenu.hasElement && floatingMenu.hasInner)
{
// Handle Opera 8 problems
floatingMenu.shiftY +=
de.clientHeight > window.innerHeight
? window.innerHeight
: de.clientHeight
}
else
{
floatingMenu.shiftY +=
floatingMenu.hasElement
? document.documentElement.clientHeight
: floatingMenu.hasInner
? window.innerHeight
: document.body.clientHeight;
}
}
}
 
floatingMenu.doFloat = function()
{
var stepX, stepY;
 
floatingMenu.computeShifts();
 
stepX = (floatingMenu.shiftX +
floatingMenu.targetX - floatingMenu.nextX) * .07;
if (Math.abs(stepX) < .5)
{
stepX = floatingMenu.shiftX +
floatingMenu.targetX - floatingMenu.nextX;
}
 
stepY = (floatingMenu.shiftY +
floatingMenu.targetY - floatingMenu.nextY) * .07;
if (Math.abs(stepY) < .5)
{
stepY = floatingMenu.shiftY +
floatingMenu.targetY - floatingMenu.nextY;
}
 
if (Math.abs(stepX) > 0 ||
Math.abs(stepY) > 0)
{
floatingMenu.nextX += stepX;
floatingMenu.nextY += stepY;
floatingMenu.move();
}
 
setTimeout('floatingMenu.doFloat()', 20);
};
 
// addEvent designed by Aaron Moore
floatingMenu.addEvent = function(element, listener, handler)
{
if(typeof element[listener] != 'function' ||
typeof element[listener + '_num'] == 'undefined')
{
element[listener + '_num'] = 0;
if (typeof element[listener] == 'function')
{
element[listener + 0] = element[listener];
element[listener + '_num']++;
}
element[listener] = function(e)
{
var r = true;
e = (e) ? e : window.event;
for(var i = element[listener + '_num'] -1; i >= 0; i--)
{
if(element[listener + i](e) == false)
r = false;
}
return r;
}
}
 
//if handler is not already stored, assign it
for(var i = 0; i < element[listener + '_num']; i++)
if(element[listener + i] == handler)
return;
element[listener + element[listener + '_num']] = handler;
element[listener + '_num']++;
};
 
floatingMenu.init = function()
{
floatingMenu.initSecondary();
floatingMenu.doFloat();
};
 
// Some browsers init scrollbars only after
// full document load.
floatingMenu.initSecondary = function()
{
floatingMenu.computeShifts();
floatingMenu.nextX = floatingMenu.shiftX +
floatingMenu.targetX;
floatingMenu.nextY = floatingMenu.shiftY +
floatingMenu.targetY;
floatingMenu.move();
}
 
if (document.layers)
floatingMenu.addEvent(window, 'onload', floatingMenu.init);
else
{
floatingMenu.init();
floatingMenu.addEvent(window, 'onload',
floatingMenu.initSecondary);
}
 
//--></script> <br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
test

Open in new window

CERTIFIED EXPERT

Commented:
Alternatively you can just do this using a fixed position div, but you dont get the same nice slide effect as if you were using JS:
<style type="text/css">
#nomove { position:fixed; left:0; top:50px; border: 1px #f00 solid;
 
 
}
</style>
<div id="nomove" >stay where you at</div> 
<div id="other">this moves </div>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br><br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
 
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
test

Open in new window

I found a solutiuon with jQuery, and I'm posting it here
		$(document).ready(function() {
			var off = $("#side").offset();
		
			$(window).scroll(function(){
				var scroll = $(this).scrollTop();
				if (scroll > off.top){
					$("#side").css("padding-top", (scroll - off.top));
				} else {
					$("#side").css("padding-top", (scroll - off.top)+10);
				}
				
			});
		});

Open in new window

Not the solution you were looking for? Getting a personalized solution is easy.

Ask the Experts
Access more of Experts Exchange with a free account
Thanks for using Experts Exchange.

Create a free account to continue.

Limited access with a free account allows you to:

  • View three pieces of content (articles, solutions, posts, and videos)
  • Ask the experts questions (counted toward content limit)
  • Customize your dashboard and profile

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.