I'm using this code to make the navigation bar stick to the top of the page after scrolling:
var nav=$('body');
var scrolled=false;
$(window).scroll(function(){
if(175<$(window).scrollTop()&&!scrolled){
nav.addClass('stuck');
$('.navigation-class').animate({marginTop:80},1000);
scrolled=true;
}
if(175>$(window).scrollTop()&&scrolled){
$('.navigation-class').animate({marginTop:0},0,function(){nav.removeClass('stuck');$('.navigation-class').removeAttr('style');});
scrolled=false;
}
});
The problem is, if the user scrolls the page up and down quickly, and the navigation is STILL animating, it will continue the animation and then suddenly jump into it's designed position, which gives a hiccup effect to the menu.
Try to scroll this page quickly to see it in live.
Is it possible to make it run smoothly like other websites?
Thanks are in order.
Edit:
After rereading the question, I realized the problem is probably that you're not cancelling the animation when the user scrolls back above 175px.
Presumably you're applying position: float to your nav element? Are you removing float as soon as the user scrolls up?
Try setting the queue option to false (see https://api.jquery.com/animate/), so the animation doesn't wait for the other one to complete.
Maybe you could try getting rid of the JQuery animation and replacing it with CSS transitions?
Maybe something like this?
var nav=$('body');
var scrolled=false;
var scrollToggle = function(){
$(window).off('scroll');
if(175<$(window).scrollTop()&&!scrolled){
nav.addClass('stuck');
$('.navigation-class').animate({marginTop:80},1000, function() {
$(window).on('scroll', scrollToggle);
);
scrolled=true;
}
else if(175>$(window).scrollTop()&&scrolled){
$('.navigation-class').animate({marginTop:0},0,function({
nav.removeClass('stuck');
$('.navigation-class').removeAttr('style');
$(window).on('scroll', scrollToggle);
});
scrolled=false;
}
};
$(window).on('scroll', scrollToggle);
I have something similar in a WIP myself. I'll post it here only slightly edited, maybe it can be useful to you.
var headerFloat = function() {
//Header
var pageHeader = $('#pageHeader'), pos = '',
headerMain = $('#headerMain'), headerMainHeight = '',
content = $('#content'), contentPadding = '',
pageTitle = $('h1.currentPage'), pageTitleTop = '';
if($(window).scrollTop() >= 95) {
pos = "fixed";
headerMainHeight = '75px';
contentPadding = '225px';
pageTitleTop = '55px';
contentHeaderTop = '130px';
}
//Header
pageHeader.css('position', pos);
headerMain.css('height', headerMainHeight);
content.css('padding-top', contentPadding);
pageTitle.css({ 'transition': 'all 0s', 'position': pos, 'top': pageTitleTop });
pageTitle[0].offsetHeight; //force "reflow" of element -- stackoverflow.com/questions/11131875/#16575811
pageTitle.css('transition', '');
};
$(document).ready(function() {
/* *** SCROLL -> FLOAT HEADER *** */
$(window).on("scroll.float", headerFloat);
});
Inputting '' (empty string) in the JQuery css function resets it to the original value. You should do that instead of .removeAttr('style');
I would also avoid the scrolled boolean. I think you need it anyway, if scrollTop < 175, you'll never be scrolled, and vice versa.
Related
jQuery(window).scroll( function(){
/* Check the location of element */
jQuery('.logoscrollbg').each( function(i){
var logo = jQuery(this).outerHeight();
var position = jQuery(window).scrollTop();
/* fade out */
if( position > logo ){
jQuery(this).animate({'opacity':'1'},100);
}else{ jQuery(this).animate({'opacity':'0'},100);}
});
});
Above is my script for a class (the header) with should blend in when the page is being scrolled down and blend out when you are on the top of the page, with other words the start.
I don't understand javascript at all, but I do a little php and I was wondering if someone could help me write there a elseif tag and later make the else tag so that is the page is loaded the class(.logoscrollbg) isn't visible and when u start scrolling it gets visible and when you get to the top it gets invisivle again :)
The script works like this right now: when I enter the site it shows the bar(bad), later when scrolling it stays or well is there(good), then when getting to top again it fades out(good).
The code inside your scroll event needs to be run when the page is loaded as well as when it scrolls.
jQuery(function() {
// object to hold our method
var scrollCheck = {};
// define and call our method at once
(scrollCheck.check = function() {
// only need to get scrollTop once
var logo, position = jQuery(window).scrollTop();
/* Check the location of element */
jQuery('.logoscrollbg').each(function() {
logo = jQuery(this).outerHeight();
/* fade out or in */
// cleaned this up a bit
jQuery(this).animate({'opacity': position > logo ? 1 : 0}, 100);
});
})();
jQuery(window).scroll(function(){
// call our method
scrollCheck.check();
});
});
It looks to me like this will only fire when you scroll. Try updating your js to this:
jQuery(window).on('scroll, load', function() {
/* Check the location of element */
jQuery('.logoscrollbg').each( function(i){
var logo = jQuery(this).outerHeight();
var position = jQuery(window).scrollTop();
/* fade out */
if( position > logo ){
jQuery(this).animate({'opacity':'1'},100);
}else{ jQuery(this).animate({'opacity':'0'},100);}
});
});
*note: You may want to fire the callback on document load instead of window.
I have a fixed .widget element that remains visible at all times. Currently however, it scrolls over the footer area. My goal is to stop the widget before it hits the footer.
CSS
.widget {
position:fixed;
height:450px;
width:300px;
}
footer {
height:450px;
width:100%;
}
My route I'm taking is currently:
jQuery
var $bodyheight = $('body').height();
var $footerheight = $('footer').height();
var $widgetheight = $('.game_widget').height();
var $pageheight = $bodyheight - $footerheight - $widgetheight;
$(window).on('scroll', function() {
console.log($(this).scrollTop())
});
My next step would be to loop through to see if scrollTop > $pageheight then update some CSS.
Is this the best way of going about this? Is there a cleaner/simpler way to achieve the same result?
I have managed to solve this quite simply. Inside the scroll function I set 2 variables, one for the position of the fixed element, the other for the position of the footer. These return the exact value from how far the top of the element is from the top of the page. For the fixed element I need to know the distance to the bottom of this element so I also include the height.
var $fixedpos = $(".game_widget").offset().top + $('.game_widget').height();
var $footerpos = $("footer").offset().top - 25; // 25 accounts for margin
Using a simple if/else the CSS is updated to display none/initial depending on whether $fixedpos > $footerpos (i.e. the fixed element is overlapping the footer).
if ($fixedpos > $footerpos) {
$('.game_widget').css('display','none');
} else {
$('.game_widget').css('display','initial');
}
This works, however there is a 'flicking' effect as the fixed element overlaps the footer. This is due to the function executing extremely rapidly. The solution to the flicker is to use this simple 'throttling' plugin that adds a short delay (of your choice) between each execution of a function - http://benalman.com/projects/jquery-throttle-debounce-plugin/
You then just need to bind the on scroll function to the throttle:
function scrolling() {
console.log($(".game_widget").offset().top + $('.game_widget').height());
console.log($("footer").offset().top - 25);
var $fixedpos = $(".game_widget").offset().top + $('.game_widget').height();
var $footerpos = $("footer").offset().top - 25;
if ($fixedpos > $footerpos) {
$('.game_widget').css('display', 'none');
} else {
$('.game_widget').css('display', 'initial');
}
};
$(window).on('scroll', $.throttle(250, scrolling)); // 250ms between executing the function
});
This 250ms delay stops the function from executing so rapidly that the flickering effect occurs.
Hope this helps others trying to solve this problem.
I have an image embedded in a container with a background image to give the effect of scrolling within the page. Initially, I had the scrolling effect take place on page load, with this simple bit of script which worked perfectly.
$(window).on("load", function () {
$(".embedded_scroller_image").animate({ scrollTop: $('.embedded_scroller_image')[0].scrollHeight}, 2500, "easeInOutCubic");
}); // end on load
However, the element is too far down the page now and I want that animation to fire when the element enters 80% of the viewport. That part is also working fine with this code here (I'm using a scroll limiter to improve browser performance)
// limit scroll call for performance
var scrollHandling = {
allow: true,
reallow: function() {
scrollHandling.allow = true;
},
delay: 500 //(milliseconds) adjust to the highest acceptable value
};
$(window).on('scroll', function() {
var flag = true;
if(scrollHandling.allow) { // call scroll limit
var inViewport = $(window).height()*0.8; // get 80% of viewport
$('.embedded_scroller_image').each(function() { // check each embedded scroller
var distance = $(this).offset().top - inViewport; // check when it reaches offset
if ($(window).scrollTop() >= distance && flag === true ) {
$(this).animate({ scrollTop: $(this)[0].scrollHeight}, 2500, "easeInOutCubic"); //animate embedded scroller
flag = false;
}
});
} // end scroll limit
}); // end window scroll function
The problem is this: I want the autoscroll to happen once and then stop. Right now, it works on entering viewport, but if I then try to manually scroll the image, it keeps pushing back down or stutters. You can't get the element to scroll normally. I attempted to use the flag in the code to stop the animation, but couldn't get that to successfully work.
How can I have this animation fire when the element is 80% in the viewport, but then completely stop after one time?
Here is a codepen I mocked up as well http://codepen.io/jphogan/pen/PPQwZL?editors=001 If you scroll down, you will see the image element autoscroll when it enters the viewport, but if you try to then scroll that image up in its container, it won't work.
Thanks!
I have tweaked your script a bit:
// limit scroll call for performance
var scrollHandling = {
allow: true,
reallow: function() { scrollHandling.allow = true; },
delay: 500 //(milliseconds) adjust to the highest acceptable value
};
$(window).on('scroll', function() {
if(scrollHandling.allow) { // call scroll limit
var inViewport = $(window).height()*0.8; // get 80% of viewport
$('.embedded_scroller_image').each(function() { // check each embedded scroller
var distance = $(this).offset().top - inViewport; // check when it reaches offset
if ($(window).scrollTop() >= distance ) {
$(this).animate({ scrollTop: $(this)[0].scrollHeight}, 2500, "easeInOutCubic"); //animate embedded scroller
scrollHandling.allow = false;
}
});
} // end scroll limit
}); // end window scroll function
I have kicked out your flag and simply made use of scrollHandling.allow declared already.
Try if it works for you :)
Cheers!
Essentially what I want to do is keep my blog posts' meta information on the screen at all times. As it is, the meta info (title, author, etc.) is displayed to the left of the post content, and I have it set up where the meta information stays on screen smoothly when I scroll down. However, I'm having an issue:
I can't get it to smoothly not scroll over the #comments DIV. It either overlaps or is jumpy, depending on how I tweak the code.
Here is the JS function I'm using:
function brazenlyScroll() {
var element = jQuery(".single-post .headline_area");
var top = element.offset().top - 50;
var elementHeight = 26 + element.height();
var maxTop = jQuery("#comments").offset().top - elementHeight;
var scrollHandler = function() {
if (jQuery(document).width() > 1035) {
var scrollTop = jQuery(window).scrollTop();
if (scrollTop<top) {
element.css({position:"relative",top:""})
} else if (scrollTop>maxTop) {
element.css({position:"absolute",top:(maxTop+"px")})
} else {
element.css({position:"fixed",top:"50px"})
}
}
}
jQuery(window).scroll(scrollHandler);
jQuery(window).resize(scrollHandler);
scrollHandler();
}
That code is included via an external JS file and is called at the bottom of the page. You can see all of this in action here: http://www.rickbeckman.org/dumber-and-dumber-and-dumber/
Any help would be greatly appreciated.
You can make the comments div shrink to right by giving it a 300px padding when meta block reaches maxTop.
I just tested ur code and was able to fix the overlapping by changing 26 to a bigger number, say about 60.
var elementHeight = 26 + element.height();
Hope this helps.
I have a question but I actually do not know how to ask.
I am trying to make a navigation bar stick on top when pass a point smoothly.
My reference is this -> http://blog.yjl.im/2010/01/stick-div-at-top-after-scrolling.html
My problem is when I use IE or Chrome to check it, there is a "blink" effect.
It is more like the scroll function will finish process after scroll over the point. So the things(HTML) after Nav will go on the top of the Nav on 0.1 ~ 0.3 secs then scroll function will finish process. Even through is short but it is visualize-able when the HTML over the nav.
However, If I use Firefox to check it, there is no such blink effect.....
May I ask what is the problem here I got?? What Should I check about??
My setting is a Anchor right before the Nav, Nav z-index = 99, and inside of the scroll function is below.
$(this).scrollTop() > $(anchor).offset().top
? nav.addClass('sticky')
: nav.removeClass('sticky')
jQuery(document).ready(function($) {
var my_nav = $('.navbar-sticky');
// grab the initial top offset of the navigation
var sticky_navigation_offset_top = my_nav.offset().top;
// our function that decides weather the navigation bar should have "fixed" css position or not.
var sticky_navigation = function(){
var scroll_top = $(window).scrollTop(); // our current vertical position from the top
// if we've scrolled more than the navigation, change its position to fixed to stick to top, otherwise change it back to relative
if (scroll_top > sticky_navigation_offset_top) {
my_nav.addClass( 'stick' );
} else {
my_nav.removeClass( 'stick' );
}
};
var initio_parallax_animation = function() {
$('.parallax').each( function(i, obj) {
var speed = $(this).attr('parallax-speed');
if( speed ) {
var background_pos = '-' + (window.pageYOffset / speed) + "px";
$(this).css( 'background-position', 'center ' + background_pos );
}
});
}
// run our function on load
sticky_navigation();
// and run it again every time you scroll
$(window).scroll(function() {
sticky_navigation();
initio_parallax_animation();
});
});