Reputation: 51
I'd like to keep a div element within the viewport when page is being scrolled. I'm currently using this snippet using jquery:
$(function() { var offset = $("#column-menu").offset(); var topPadding = 25; $(window).scroll(function() { if ($(window).scrollTop() > offset.top) { $("#column-menu").stop().animate({ marginTop: $(window).scrollTop() - offset.top + topPadding }); } else { $("#column-menu").stop().animate({ marginTop: 25 }); }; }); });
It works great but what happens is that the element disappear upon scrolling and then comes down from the top
-- what I would like instead -- The element stops as soon as its top border reaches the top of the viewport, no animation, no gliding no nuttin'.
It should be ie6,ie7 and ie8 compliant... Any suggestions (even with prototype) would be great. Thanks.
Upvotes: 5
Views: 3441
Reputation: 1441
I just completed a plugin that will do this as well. I had problems attempting to change the element's position from fixed to absolute and back again whenever it hit the top or bottom of the viewport. It didn't work for me under different screen resolutions since I had a need to set the left property. Basically just reference the plugin and call this on the element you want to scroll:
$myDiv.fixposition({boundingElement:myBoundary}) //myBoundary is the element you want your scrolling div to remain within.
/**
* Enables an element to be fixed in position within a specified bounding element.
* Usage: $("#myElementToBeFixed").fixposition();
* Provide a data structure with the following elements if you want to override the defaults:
* boundingElement - the element to limit the fixed position within
* bottomOffset - the amount to bufferhe fixed element from the bottom (of the specified bounding element)
*/
(function($) {
$.extend($.fn, {
fixposition: function(opts) {
return this.each(function() {
var defaults = {
boundingElement: "",
bottomOffset: 20
};
var options = defaults;
if (typeof(options) != 'object') options = { };
options = $.extend(options, opts);
$this = $(this);
var $boundEl = $("#" + options.boundingElement);
var bottomBound = $boundEl.offset().top + $boundEl.height();
var maxTop = bottomBound - $this.height() - options.bottomOffset;
var minTop = $this.offset().top;
var newTopPos = null;
var parentTopOffset = $this.parent().offset().top;
if($("body").length > 0 && options.boundingElement != "") {
$(window).scroll(function () {
var scrollY = $(window).scrollTop();
if($this.length > 0) {
if ($this.offset().top != (scrollY - parentTopOffset)) {
newTopPos = scrollY - parentTopOffset;
}
if (newTopPos != null) {
if (newTopPos > maxTop - parentTopOffset) {
newTopPos = maxTop - parentTopOffset - options.bottomOffset;
} else if (newTopPos < minTop - parentTopOffset) {
newTopPos = minTop - parentTopOffset;
}
$this
.stop()
.css({"top": newTopPos});
}
}
});
}
});
}
});
})(jQuery);
Upvotes: 0
Reputation: 4381
I am currently doing something very similar to this to keep a little summary info header at the top of long tables. Basically when you scroll past X (in this case 180px) then the div gets repositioned fixed to the top of the page. If you scroll back up past X then the div gets set back to its original position. No animations and no frills!
window.onscroll = function()
{
if( window.XMLHttpRequest ) {
if (document.documentElement.scrollTop > 180 || self.pageYOffset > 180) {
$('#StickyHeader').css('position','fixed');
$('#StickyHeader').css('top','0');
} else if (document.documentElement.scrollTop < 180 || self.pageYOffset < 180) {
$('#StickyHeader').css('position','absolute');
$('#StickyHeader').css('top','0px');
}
}
}
Upvotes: 2