I am using the following code to make a fixed div ("two") to only remain fixed when scrolling between two absolute positioned divs ("one" and "footer").
But I am having one problem, when the browser window is made smaller or larger the distance between the footer and where the fixed div ("two") becomes unfixed increases or decreases, so that the fixed div becomes unfixed before the footer gets to it or after the footer has passed it.
How can I solve this? Can anyone help?
The DEMO here.
UPDATE (21 JULY 2016):
It seems that what is happening is:
Because div "leftside" has its width set as a percentage, when the browser window gets dragged smaller the div "leftside" gets higher to fit its content. This leaves div "two" hanging higher above div "footer" because div "two" lowest possible vertical position is set on page load.
I need to maintain the responsive design, and I can't have the page reloading when scaling the browser window because of other functionality in my website. Scaling the page and then refreshing it in the browser actually does reset things properly, but reloading is not an option for me.
Perhaps options to solve this:
Is there a way to reset the lowest possible position of div "two"
when the window is scaled?
Or actually even better; perhaps resetting the lowest possible
position of div "two" very frequently and automatically, or
everytime the user does something on the webpage or scaling the
browser window. This because I have collapsible segments in the div
"leftside" that will make this div higher or less high without even
scaling the browser window.
I guess adaptation needs to be made in this section of the code(?):
$window.resize(function()
{
bumperPos = pos.offset().top;
thisHeight = $this.outerHeight();
setPosition();
});
$window.scroll(setPosition);
setPosition();
};
Here the full script:
var window = this;
$.fn.followTo = function (from, bumper) {
var $this = this,
$window = $(window),
$from = $(from),
$bumper = $(bumper),
$startPos = $from.offset().top + $from.height(),
bumperPos = $bumper.offset().top,
thisHeight = $this.outerHeight(),
setPosition = function(){
if ($window.scrollTop() < $startPos) {
$this.css({
position: 'absolute',
top: $startPos
});
} else if ($window.scrollTop() > (bumperPos - thisHeight)) {
$this.css({
position: 'absolute',
top: (bumperPos - thisHeight)
});
} else {
$this.css({
position: 'fixed',
top: 0
});
}
};
$window.resize(function()
{
bumperPos = pos.offset().top;
thisHeight = $this.outerHeight();
setPosition();
});
$window.scroll(setPosition);
setPosition();
};
$('#two').followTo('#one', '#footer');
I've made three modifications:
The pos variable was not defined, it should be bumper.
Reset $startPos on resize—this fixes the problem of element(s) above the sticky element changing their height/position on resize.
Moved the fixed element's top value to a parameter in the followTo function, and take it in consideration when switching the fixed/absolute positions for a smoother transition.
Here's the updated fiddle.
$.fn.followTo = function (from, bumper, fixedOffsetTop) {
var $this = this,
$window = $(window),
$from = $(from),
$bumper = $(bumper),
$startPos = $from.offset().top + $from.height(),
bumperPos = $bumper.offset().top,
thisHeight = $this.outerHeight(),
setPosition = function(){
if ($window.scrollTop() < $startPos - fixedOffsetTop) {
$this.css({
position: 'absolute',
top: $startPos
});
} else if ($window.scrollTop() > bumperPos - thisHeight - fixedOffsetTop) {
$this.css({
position: 'absolute',
top: (bumperPos - thisHeight)
});
} else {
$this.css({
position: 'fixed',
top: fixedOffsetTop
});
}
};
$window.resize(function()
{
$startPos = $from.offset().top + $from.height();
bumperPos = $bumper.offset().top;
thisHeight = $this.outerHeight();
setPosition();
});
$window.scroll(setPosition);
setPosition();
};
$('#two').followTo('#one', '#footer', 30);
Related
I have this jsfiddle: https://jsfiddle.net/3ncyxnzt/
It currently works well as far as always stopping at a specified margin from the top of the page, but I'd like to make it also stop at the bottom, before it goes under/over the footer. Any ideas on how to make that moving red box stop right above the green footer? The height of the footer is 1000px, so I'd somehow need to set the moving box to stop at 1000px from the bottom.
Here's the code I have so far:
(function(jQuery) {
var element = jQuery('.move'),
originalY = element.offset().top;
var topMargin = 110;
element.css('position', 'relative');
jQuery(window).on('scroll', function(event) {
var scrollTop = $(window).scrollTop();
element.stop(false, false).animate({
top: scrollTop < originalY
? 0
: scrollTop - originalY + topMargin
}, 200);
});
})(jQuery);
I modified following line by adding static value 290 and it reached to bottom.
scrollTop - originalY + topMargin + 290
Is this what you trying to achive?
(function(jQuery) {
var element = $('.move'),
originalY = element.offset().top,
otherDiv = 1000,
staticHeight = $('.other-div').height()-$(element).height(); // Fixed number to stop the move-element before the footer
var topMargin = 110;
jQuery(window).on('scroll', function(event) {
var offset = element.offset().top;
var scrollTop = $(window).scrollTop();
// Check if the move-block gets under the footerblock
if(scrollTop < otherDiv){
element.stop(false, false).animate({
top: scrollTop - originalY + topMargin
}, 200);
}else{
element.stop(false, false).animate({
top: staticHeight //If so, make sure it gets on top of the footerblock staticly
}, 200);
}
});
})(jQuery);
I think you need an if/else statement to check if the block gets behind the height of the div called "other-div".
See the working example here: https://jsfiddle.net/crix/z578c9bo/
Hope it helps!
I have a div that I want to keep position: fixed when scrolling between two points.
For example, it should remain fixed only between the height of it's container div
I've done the following:
$window.scroll(function(e) {
pos = $('.container-element').height();
if ($window.scrollTop() > pos) {
$(scroll-element).css({
position: 'relative',
});
} else {
$(scroll-element).css({
position: 'fixed',
});
}
});
However, this doesn't stop the scroll-element from becoming relative on reaching the end of the container-element. What should I do to achieve the intended behavior?
EDIT:
JSFiddle: http://jsfiddle.net/09760d60/
I think You should remove fixed position when $(window).scrollTop() > containerHeight-childHeight
$(document).ready(function(){
$(window).scroll(function(e) {
containerHeight = $('.container-element').height();
childHeight = $(".scroll-element").height();
if ($(window).scrollTop() > containerHeight-childHeight) {
$('.scroll-element').removeClass('fixed');
} else {
$('.scroll-element').addClass('fixed');
}
});
});
Please check updated fiddle
http://jsfiddle.net/PrashantShirke/1u991v1j/
You should check the top and bottom bounds of your container, and compare it with the top and bottom bounds of your scroll element :
$(document).ready(function(){
$(window).scroll(function(e) {
containerTop = $('.container-element').offset().top;
containerBottom = $('.container-element').height()+$('.container-element').offset().top;
scrollEl = $('.scroll-element').height();
if ($(window).scrollTop() >= containerTop && $(window).scrollTop()+scrollEl <= containerBottom) {
$('.scroll-element').css({
"top":$(window).scrollTop()+"px"
});
}
});
});
Exemple
$(window).scrollTop() < containerTop: scroll element is at top of content
$(window).scrollTop()+scrollEl > containerBottom: bottom of scroll element is at bottom of content
If scroll element has to move, adjust its top property while being absolutelly positioned by CSS.
I think it would be more robust to check the bottoms of the container and window, not the heights of the container and child.
$(document).ready(function(){
var $window = $(window);
var $container = $('.container-element');
var $scroll = $('.scroll-element');
var containerBox = $container[0].getBoundingClientRect();
$window.scroll(function(e) {
var scrollBottom = $window.scrollTop() + $window.height();
var canSeeContainerBottom = scrollBottom > containerBox.bottom;
$scroll.css('position', canSeeContainerBottom ? 'relative' : 'fixed');
});
});
http://jsfiddle.net/bryandowning/09760d60/14/
I have floating div which content is dynamically populated using js function.
I'm using following code to make this div float
// Stick the #nav to the top of the window
var nav = $('#right-div');
var navHomeY = nav.offset().top;
var isFixed = false;
var $w = $(window);
$w.scroll(function() {
var scrollTop = $w.scrollTop();
var shouldBeFixed = scrollTop > navHomeY;
if (shouldBeFixed && !isFixed) {
nav.css({
position: 'fixed',
top: 0,
left: nav.offset().left,
width: nav.width()
});
isFixed = true;
}
else if (!shouldBeFixed && isFixed)
{
nav.css({
position: 'static'
});
isFixed = false;
}
});
});
sometimes when enough content items is added this div height is larger than windows and part of div content is not visible at all, it stays bellow page margin.
So I'm thinking on js function where content is generated before adding to floating div to calculate windows height and floating div and simply apply bottom margin to floating div
if ($(window).height() < $("#right-div").height()) {
alert("float div is larger than window");
$("#right-div").css({bottom:100});
}
on firebug I see this applied bottom margin (100px) but part of div content is still hidden.
I have a problem with a JavaScript I'm developing for my website. I have images which opens on hovering over them.
First my script calculates if the image should be displayed on the right or on the left of my window:
$("html,body").live("mousemove", function (e) {
//console.log("mousemove: "+e.pageX)
var width_window = $(window).width();
var center = width_window / 2;
if (e.pageX < center) {
side = 'left';
} else {
side = 'right';
}
});
Then, once we know on which side of the window the image will be displayed, I have another script to resize the image, depending of the height & width of my window, including the margins:
this.resizeImg = function (img, offset) {
var d = new Date();
//console.log(d, side);
var window_height = $(window).height();
var img_height = $(img).height();
var img_top = $(img).offset().top;
var window_width = $(window).width();
var img_width = $(img).width();
var img_left;
side == 'left' ? img_left = offset.left : img_left = window_width - offset.left;
console.log(window_width, img_left)
var image_resize_height = window_height - img_top - 20;
var image_resize_width = window_width - img_left - 20;
if (img_height + img_top > window_height && img_width + img_left > window_width) {
console.log("h w")
if (image_resize_width > image_resize_height) {
$(img).css('height', image_resize_height + 'px').css("width", "auto");
} else {
$(img).css('width', image_resize_width + 'px').css("height", "auto");
}
} else if (img_height + img_top > window_height) {
//console.log("h")
$(img).css('height', image_resize_height + 'px').css("width", "auto");
} else if (img_width + img_left > window_width) {
//console.log("w")
$(img).css('width', image_resize_width + 'px').css("height", "auto");
} else {
//console.log("non")
}
};
It almost works, but sometimes my images exceed the window width or height. I can't find the solution...
Here is my CSS:
.vignette {
max-height: 800px;
max-width : 800px;
z-index : 2;
top : 25px;
}
.info{
position : relative;
}
.info img {
position : absolute;
display : none;
cursor : pointer;
}
My full script in jsFiddle: http://jsfiddle.net/CrnNZ/
Here is the link to my website : http://olivierlellouche.com/
Thanks a lot for your help !
Are you taking care of the fact that you are moving the image down 25px in:
.vignette {
top : 25px;
}
The only height adjustment I see is 20px:
var image_resize_height = window_height - img_top - 20;
You may just need to subtract few more pixels to your calculations?
Or better yet:
var img_top = $(img).offset().top;
May be top of the offset area and not the raw top of the image. In which case, you still need to subtract 25px for that.
(From your website) The other thing that may be useful is to always enable, or always disable the vertical scroll-bar on the right. Or re-size the text area to be smaller than the available area when their isn't a scroll-bar. (Unfortunately, I could not get your jsfiddle to work at all and the only error from their I could view was vertical calculation errors. I could not see any horizontal errors.)
Does the problem continue if you subtract a few more pixels off the height?
I can't tell from your code but, does it place the image then re-size it? It may be better idea to calculate the size available before trying to place the image, that way it never changes sizes once it is placed.
EDIT:
After looking at your webpage with much smaller sized window I thought of something else. $(window).height() is not the same as $(document).height(). See: $(window).height() vs $(document).height You may need to calculate the remaining page differently if they are not the same.
I have a vertically oriented vertical navigation bar, that I would like to make stop at the end of #contact. It will need to resume scrolling again if the user scrolls back up.
What is the best way to achieve this?
javascript being used:
$(function() {
$.fn.scrollBottom = function() {
return $(document).height() - this.scrollTop() - this.height();
};
var $el = $('#nav>div');
var $window = $(window);
var top = $el.parent().position().top;
$window.bind("scroll resize", function() {
var gap = $window.height() - $el.height() - 10;
var visibleFoot = 340 - $window.scrollBottom();
var scrollTop = $window.scrollTop()
if (scrollTop < top + 10) {
$el.css({
top: (top - scrollTop) + "px",
bottom: "auto"
});
} else if (visibleFoot > gap) {
$el.css({
top: "auto",
bottom: visibleFoot + "px"
});
} else {
$el.css({
top: 0,
bottom: "auto"
});
}
}).scroll();
});
jsfiddle
I believe this is the code you are looking for:
$(function() {
var $Nav = $('#Nav');
var $window = $(window);
var $contact = $('#contact');
var maxTop = $contact.offset().top + $contact.height() - $Nav.height();
window.navFixed = 1;
$window.bind("scroll resize", function() {
var currentTop = $window.scrollTop();
if (currentTop <= maxTop && window.navFixed == 0) {
$Nav.css({
position: 'fixed',
top: '5%'
});
window.navFixed = 1;
} else if (currentTop > maxTop && window.navFixed == 1) {
$Nav.css({
position: 'absolute',
top: maxTop
});
window.navFixed = 0;
}
}).scroll();
});
The #Nav element contains the CSS you had originally specified: position: fixed; top: (...). When the document is ready, the variable maxTop is calculated based on the #contact element's top and height.
On the scroll and resize event, the variable currentTop is calculated as the current scroll position. If this value is lower than maxTop, then #Nav is set to the original CSS; if the value is higher, new CSS styles are applied: position: absolute; top: maxTop;
window.navFixed is used to prevent the CSS to be constantly updated while scrolling. I'm sure that bit can be improved, however, it demonstrates its purpose.
Check out the JSFiddle for the full HTML..
PS. There's a minor bug in your code, where #Nav refers to the <ul> element, rather than the <nav> element. However, the moving element is the <ul>, when it should be <nav>.