$(document).scroll(function(e){
var eTop = $(this).scrollTop()
$('.popup').each(function(i){
log(eTop);
if($(this).offset().top - topLimit <= eTop){
$(this).fadeIn();
}
});
});
I got this Fiddle, where i want to use fadeIn() on elements, when they are 100 pixels from the top of the screen. I give JavaScript 3 values to use in comparison, to know when that should happen, but I doesn't work... I measured the values myself via a log-function I used, and it should work, but it just doesn't... I was hoping anyone maybe could see an error I cant... Thanks
The problem is that the image is hidden, so offsetTop doesn't work.
Removing
.popup{
display:none;
}
fixes it.
Demo
It can't work because:
var eTop = $(this).scrollTop()
and
$(this).offset().top
is the same value and your IF condition is never met.
The problem is that your image is hidden, so offsetTop won't work as #Oriol point out. but you can get around with that by measuring the text height, because the image is just after the text. working version is this: http://jsfiddle.net/D6tE2/6/
$(document).scroll(function(e){
var eTop = $(this).scrollTop()
$('.popup').each(function(i){
if($('p').height() < eTop){
$(this).fadeIn();
}
});
});
Another solution
There's really two problems at play here:
1: display: none takes your object out of the correct DOM position, so when your img is hidden, the calculation on its page offset is always the same as scrollTop (i.e., at 0,0 relative to the document root).
2: Even if you compensate for this by using something like opacity: 0 - which places it in the correct place in the DOM, fadeIn expects display: none to be set, so we have to manually hide() the entry and reset it's opacity, then fadeIn.
You could just animate it setting the opacity to 0 to start with. To have the same effect as display none, you can set the position to absolute at first. I also added a check for the show class so the code does not run again when it is already shown
http://jsfiddle.net/D6tE2/14/
$(document).scroll(function(e){
var eTop = $(this).scrollTop()
$('.popup').each(function(i){
log(eTop);
if(!$(this).hasClass('show') && $(this).offset().top < eTop){
$(this).addClass('show').animate({'opacity' : '1'}, 500);
}
});
});
CSS
.popup{
opacity: 0;
position: absolute;
}
.show {
position: static;
}
Related
I am trying to get the height of my navigation and apply it to a margin-top so I can offset my banner. My navigation is fixed so I'm trying to compensate for that so my banner isn't hidden underneath.
// Offset Banner to Height of Navigation
function bannerOffset() {
var bannerTop = $('.x-navbar').height();
$('#banner-carousel').css('margin-top', bannerTop);
}
This, I thought would do it, but it doesn't reflect anything at all in the front-end.
UPDATE
$(document).ready(function() {
var bannerTop = $('.x-navbar').outerHeight();
$('.x-main').css('margin-top', bannerTop);
$(window).scroll(function() {
var bannerTopScroll = $('.x-navbar.scroll').outerHeight();
if ($(document).scrollTop() > 1) {
$('.x-main').css('margin-top', bannerTopScroll);
}
});
});
So I thought I had this, but on load, the margin-top of .x-main is 245px. When I scroll it becomes 85px. I can see the numbers go down to that. The issue is when I scroll back up to the top the value doesn't go back to 245px. It's not very consistent, but I often get 144px. I should add that, and this is probably why, I have another function that changes the height of my .x-navbar when .scroll is added to it.
$(window).scroll(function() {
if ($(document).scrollTop() > 1) {
$('.x-navbar').addClass('scroll');
} else {
$('.x-navbar').removeClass('scroll');
}
});
So I am not sure how to make this all smooth and working properly. If I reload the page the .x-mainis back to 245px. When I scroll back to the top it's not calculating properly.
Your code works. Maybe you want to use $.outerHeight() instead, your selectors are wrong, or you're experiencing margin collapsing.
It's worth noting that $.height() returns an integer value, so in your $.css() line, you should change bannerTop to bannerTop + 'px' so that the CSS has a unit and not just a number... but it looks like jQuery is doing that automagically for me here. You might try it and see.
var bannerTop = $('.x-navbar').height();
$('#banner-carousel').css('margin-top', bannerTop);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="x-navbar">x-navbar<br>x-navbar<br>x-navbar<br>x-navbar<br>x-navbar<br>x-navbar<br>x-navbar<br>x-navbar<br></div>
<div id="banner-carousel">banner carousel</div>
The code below is test code I'm using. The blue bar is supposed to stick to the top of the screen when it reaches the top.
This works on my browser, but the reason I'm here is because when it sticks to the top, it all of a sudden becomes smaller. As you see the blue bar starts with a full width across the container, but on my computer/browser, after it sticks to the top, the div shrinks to just the size of the text.
To make matters worse, I cannot reproduce the problem on jfiddle, because in jfiddle it doesn't work at all! (The images are just there to create a scroll).
Here is the jfiddle
Here is the jquery:
var titlePosition = $('.title').offset().top;
$(window).scroll(function () {
var scrollBar = $(this).scrollTop();
if (scrollBar > titlePosition) {
$('.title').css("top", "0px");
$('.title').css("position", "fixed");
} else {
$('.title').css("position", "relative");
}
});
Try this code:
Fiddle
CSS:
.title {
font-size:200%;
background-color:blue;
width:100%
}
Update your code:
if (scrollBar > titlePosition) {
$('.title').css("top", scrollBar+"px");
$('.title').css("position", "fixed");
} else {
$('.title').css("position", "static"); //otherwise it will still get that top value and cause unwanted position;
}
Just add this css:
.title {
...
width: 100%; /*This does the trick*/
}
Here you have it working: http://jsfiddle.net/edgarinvillegas/yPWAC/3/
Cheers
Set left to 0 as well. Additionally, some optimizations.
I prefer appending/removing classes to put all your CSS in your stylesheet. Saves you from problems later on when the code gets huge (who would be looking for CSS in JS files anyway?).
Also, cache objects. Everytime you fire scroll, your code fetches every single .title in the DOM and generates a jQuery object. Not very optimal. Instead, get all .title and just do the modifications on each scroll.
CSS:
.title.fixed {
position:fixed;
left:0;
right:0;
top:0;
}
JS:
var titlePosition = $('.title').offset().top;
var win = $(window);
var title = $('.title');
win.scroll(function () {
var scrollBar = win.scrollTop();
if (scrollBar > titlePosition) title.addClass('fixed');
else title.removeClass('fixed');
});
As for your non-working fiddle, you forgot to include jQuery. That should be found on the top left.
Try giving z-index:999 or, using jQuery - $('.title').css("z-index", "999");
Rest looks ok.
var titlePosition = $('.title').offset().top;
.top is not a function. offset() returns an object containing the properties top and left
Replace with:
var titlePosition = $('.title').offset();
You can now access the properties like so:
titlePosition.top or titlePosition.left
reference: .offset() http://api.jquery.com/offset/
Thanks for all the feedback.
Even though it helped improve, in the end the div was still resizing. Fixing the width to specific values was not responsive enough.
I finally stumbled upon a solution, based on all the advice:
http://jsfiddle.net/yPWAC/8/
var titleWidth = $('.title').width()
/*then after the div is fixed I change the width */
$('.title').css("width",titleWidth);
I made jquery hold the original width of the div, then change the width of the sticky div to whatever that value is.
For some reason, even if I defined the original width in CSS, the new sticky width would still come out a different size in the browser. So this method gives it the same width as the original (whatever it may be)
I have a sticky nav I'm working on, I was able to gather some code from some other posts, however I'm running into one issue, the nav area I'm hiding after scroll won't show back up when scrolling to the top of the page. I attempted to write an else if statement, but no luck, thanks.
$(window).scroll(function(){
if($("#navheader").offset().top <= $(window).scrollTop)
$("#navheader").css({"display":"block","top":"0px", "left":"0px"});
else
$("#navheader").css({"display":"none"});
});
This might be easier
Looks like the issue was that you need a () after scrollTop on window.
var n = $("#navheader");//get nav
var nh = n.offset().top;//get nav offset
var go = true;//toggle execute so it doesn't fire on every match
$(window).scroll(function(){
var wh = $(this).scrollTop();//window scroll
if(wh <= nh && !go) {//show
n.show();
go = true;
} else if (wh > nh && go) {//hide
n.hide();
go = false;
}
});
made a fiddle: http://jsfiddle.net/filever10/cxJ6a/
edit: added a go toggle to stop fire on every match of the if/then. this way it fires once each way.
If you console.log:
console.log($("#navheader").offset().top)
On the scroll event, you will see that once the IF statement becomes true it will return always 0. Since the element is fixed and it has top: 0 it will always have 0.
The solution you ask?
Make the offest global variable and check it.
var navOff = $("#navheader").offset().top;
$(window).scroll(function(){
if(navOff <= $(window).scrollTop())
$("#navheader").css({"display":"block","top":"0px", "left":"0px"});
else
$("#navheader").css({"display":"none"});
});
But since your $("#navheader") is probably set to display: none and it will probably return 0 even this way...
So you have a few options.
Make some holder of the navigation and target it's offest.
Hard code the value.
Make it visibility: hidden; instead of display: none; (that way you can target the offest)
I have fixed div on bottom of my page that works well. I wonder if there is some simple way to make it "stop" on some place in page when user srolls down to it. I want it to remain fixed on bottom, until user scrolls down to some defined place on page and than stick it to the page and scroll like the rest of content. Any suggestions?
I tried setting something up on jsfiddle. While I was writing it up, I see that others have posted their alternatives. In case mine helps in any way: http://jsfiddle.net/PnUmM/1/
I set the position to relative in the CSS, calculate where it is on document load to keep the info aside and then set it to fixed.
var sticky_offset;
$(document).ready(function() {
var original_position_offset = $('#sticky_for_a_while').offset();
sticky_offset = original_position_offset.top;
$('#sticky_for_a_while').css('position', 'fixed');
});
$(window).scroll(function () {
var sticky_height = $('#sticky_for_a_while').outerHeight();
var where_scroll = $(window).scrollTop();
var window_height = $(window).height();
if((where_scroll + window_height) > sticky_offset) {
$('#sticky_for_a_while').css('position', 'relative');
}
if((where_scroll + window_height) < (sticky_offset + sticky_height)) {
$('#sticky_for_a_while').css('position', 'fixed');
}
});
I made this up for you: http://jsfiddle.net/XCYFG/1/.
$(document).ready(function() {
window._div1 = $('#div1'); //selector is expensive
window._window = $(window);
$(window).scroll(function(e) {
_div1.css("top",
Math.min(_window.height(),
window.scrollY + 100)
+ _window.height() - _div1.height() - 110);
}).scroll();
});
I have a plugin that does the opposite - it's in the flow of the webpage, and when the user scrolls past it, it gets fixed to the viewport. What it actually does though is apply a css class to the element, so you should be able to use it as is.
You can find the plugin here:
https://github.com/hanssonlarsson/jquery-fixedscroll
Then I would suggest you have your element in the flow of your webpage:
<div id="sometimesFixed">content</div>
With css:
#sometimesFixed {
position: fixed;
bottom: 0;
}
#sometimesFixed.scroll {
position: static;
}
And apply the plugin like so, in your JavaScript:
$('#sometimesFixed').fixedscroll({className: 'scroll'});
There is also a more general plugin, very new, called jquery-waypoints. The idea is to bind any code to "waypoints", points on the webpage where, when the user scrolls past them, some code is executed.
https://github.com/imakewebthings/jquery-waypoints
It's probably more optimized and a better fit than my plugin, but YMMV!
I have 2 divs and one is nested in the other. I want to get the child div position relative to browser window. The use case is this: when user scroll down browser, I want to detect the position of the child div and if it is 100px above the bottom of the browser window, I want to fade it out slowly.
How do I do that with jQuery? The 2 divs have relative position or absolution position but not fixed position.
Try this:
$(window).scroll(function () {
var distanceFromBottom = 100;
if ( ( $("#outerdiv").offset().top + $("#innerdiv").height() - $(window).scrollTop() ) > $(window).height() - distanceFromBottom ) {
$("#innerdiv").fadeOut("slow");
} else {
$("#innerdiv").fadeIn("slow");
}
})
You didn't state if you wanted the #innerdiv to fade back in if greater than 100 pixels from the bottom, but I wrote this assuming that you did... In this case, you would need to detect the offset of the #outerdiv if you want the #innerdiv to fade back in as an invisible element has no position.
If you don't want the #innerdiv to fade back in then change the if statement to look at the #innerdiv element and remove the else portion of the function.
Edit: Looking at your example page, I'm guessing you wanted this effect to work on the music player. Since, it's probably not the best idea to fade or slowly hide an embedded object using jQuery - it just doesn't animate well - so, I just did it abruptly. The above script will still work, but as you can see in the revision below, you don't have to use 2 Divs, I used the div and the embedded object within it. The outer div should closely wrap the inner div for this script to work, so you can't use the div with id "container-msg" in this case.
$(window).scroll(function () {
var distanceFromBottom = 100;
if ( ( $(".windowMediaPlayer").offset().top + $(".windowMediaPlayer object").height() - $(window).scrollTop() ) > $(window).height() - distanceFromBottom ) {
$(".windowMediaPlayer object").hide();
} else {
$(".windowMediaPlayer object").show();
}
})
I modified your example and saved it to this pastebin so you can see it working.
Edit: Oops, you said you wanted it to disappear when it got closer to the bottom... I just changed the "<" to ">" and now it should do what you want. I updated the pastebin code too.
var inner_offset = $("#innerdiv").offset();
var window_size = $(window).height();
if( ( inner_offset.top + $("#innerdiv").height() ) > window_size - 100 )
$("#innerdiv").fadeOut("slow");
Not vetted, but should give you the general idea.
offset at the
jQuery documentation