Javascript for jumping to top and back on scroll - javascript

I have a function to let a container jump to the top upon scrolling 100px, and jump back in position once scrolled to the top again. I am working to disable this on smaller devices but the code I use also breaks the behaviour.
$(window).scroll(function() {`
//After scrolling 100px from the top...
if ( $(window).scrollTop() >= 72 || w > 920 ) {
$('#container').css('top', '0px');
//Otherwise remove inline styles and thereby revert to original stying
} else {
$('#container').attr('style', '');
}
});
UPDATE: this code should actually make the container jump to the former position when you scroll to the top again. The problem is in 'w > 920'. I need that to disable the behaviour on smaller devices but it also breaks the function. I guess because of the 'AND' statement. The window width stays the same so possible because of that the revert breaks.
Not working fiddle
https://jsfiddle.net/xm1yq4to/
Working fiddle
https://jsfiddle.net/s15g7nup/
Is there another way to specify the devicewidth for this?

I ended up doing this in a different way bij not checking the device with but a change of class
$(document).ready(function() {
// run test on initial page load
checkSize();
// run test on resize of the window
$(window).resize(checkSize);
});
//Function to the css rule
function checkSize(){
if ($(".desktop-menu").css("display") == "block" ){
$(window).scroll(function() {
//After scrolling 100px from the top...
if ( $(window).scrollTop() >= 100 ) {
$('#container').css('top', '0px');
}
//Otherwise remove inline styles and thereby revert to original stying
else {
$('#container').attr('style', '');
}
});
}
return false;
};

Related

Remove scroll function upon window resize/media query

I have a navigation menu set to display:none, which appears upon scroll and disappears once back at the top.
Is there a way to disable the scroll function once I reach a certain breakpoint (ex. max-width: 786px) and display the menu?
Javascript
$(window).on("scroll", function() {
if($(window).scrollTop()) {
$('nav').addClass('show');
}
else {
$('nav').removeClass('show');
}
})
CSS
.show {
display: block
}
You can solve this using either javascript or CSS, however I would personally go with the javascript one.
First up, for a javascript solution, the function you need is:
window.innerWidth
It will return the entire window width not including scroll bars. Read more about it here.
So, as Temani Afif suggested, you would write a test inside your scroll function to check for the desired window width like so:
$(window).on("scroll", function() {
if (window.innerWidth <= 786) return;
// Your other code here
})
For a purely CSS solution, you could override the effect of the 'show' class with a media query:
.show {
display: block
}
#media screen and (max-width: 786px) {
nav {
display: block !important
}
}
More on media queries here
You can activate/deactivate the scroll listener on browser resize. This way your scroll listener wont be called everytime user scrolls when browser width is more than 786px.
var scrollListenerActive = false;
var handleScrollListener = function() {
if( $(window).width() < 786 && !scrollListenerActive ) {
$(window).on("scroll", function() {
if($(window).scrollTop()) {
$('nav').addClass('show');
}
else {
$('nav').removeClass('show');
}
});
scrollListenerActive = true;
} else {
$(window).off("scroll");
scrollListenerActive = false;
}
}
$(document).ready(handleScrollListener); // attach the listener on page load
$(window).resize(handleScrollListener); // attach/remove listener on window resize
That's a good strategy above, however the event you want to listen for is simply 'resize', on the window object (some older browsers can do it on any dom element, but better to be consistent and current with the standard).
So something like:
window.addEventListener('resize',function(){
if(window.innerWidth >= 768){
document.body.style['overflow-x'] = 'hidden';
}
else{
document.body.style['overflow-x'] = 'auto';
}
});
You can trade 'auto' for 'scroll' if you want the scrollbar to always show when less than 768.
Similarly, you can switch out 'overflow' instead of 'overflow-x' if you want to affect both scrollbars.
Keep in mind that the event tends to fire for every width and height change as the window is resized, in case you have other logic that might have an issue with firing many times (thousands or more) as it is resized.
This also works on maximize/restore, as they trigger the resize event as well.
Here's MDN's doc on the resize event if needed:
https://developer.mozilla.org/en-US/docs/Web/Events/resize
This is vanilla javascript, so it should work whether you're using a lib like jquery or not.

Animate in div with image when scroll down to the bottom of where the image using jQuery

I have static images that I want to animate in when the user scrolls to the bottom of where they would be (the bottom of their rectangle). I've tried using the code:
$(window).on("scroll", function(){
if($("body").scrollTop() === 500){
$(window).off("scroll");
//Do stuff here
$('.context_right').fadein(4000);
}
});
With .context_right being the that contains the image I want to slide in from off the right side of the screen. I have tested this in Chrome debugger but there is not animation at all and I can't see why it's not being fired when scrolling down.
You're checking if the scroll position of the window is exactly equal to 500px. This is likely incorrect. You probably only want to check and see if the user has scrolled past 500px.
Consider changing:
if($("body").scrollTop() === 500)
to:
if($("body").scrollTop() >= 500)
Also, be careful with this:
$(window).off("scroll");
If you use any libraries that rely on the scroll event on the window, you would be unbinding all of those events in addition to your own.
Consider refactoring to something like the following:
var scrollAnimateIn = function(){
if($("body").scrollTop() >= 500){
$(window).off("scroll", scrollAnimateIn);
//Do stuff here
$('.context_right').fadein(4000);
}
};
$(window).on("scroll", scrollAnimateIn);

Hide/Show Nav on Vertical Scroll

I've implemented a scroll based state change on my nav bar, which fades in a fixed position nav at the screen top after the user scrolls down a lengthy page and then hides it and puts it back in it's relative position again as they scroll back up to see the top of the page. It works great 90% of the time. Here's my code..
function scrollNavReveal() {
var nav = $('nav.nav-primary');
$(window).scroll(function(){
var scrollpos = $(this).scrollTop();
if ((scrollpos > 200) && (scrollpos < 800)) {
nav.fadeOut(500);
}
else if (scrollpos > 800) {
nav.css({"position": "fixed", "width": "100%"}).fadeIn(500);
}
else {
nav.css({"position": "relative", "width": "100%", "display": "block"});
}
});
}
The issue is that when I scroll to the page top very quickly with my mouse, sometimes the nav does not appear. I have to make a small scroll on the mouse and then it pops back into place. This also happens when I use my scroll to top function which is initiated when a user clicks the 'go to top' button in the footer.
function go_to_top() {
$('a.naada-top').click(function() {
$('html, body').animate({scrollTop:0}, 'slow');
})
}
In the go_to_top function I believe the .animate({scrollTop:0}, 'slow'); does not take into account the height of the nav itself, which isn't currently in position: relative; (hence not in the normal DOM flow/scroll height).
Both issues seem very similar, but slightly different and they can be seen and tested here naada.staging.wpengine.com
Thanks for your help!
I recommend adding an if statement for < 200 rather than an else at the end of the statement. If you don't have to roll through each if statement and prove them false the processing speed will be quicker, which might catch the quicker scroll a little better. I also use the (document).scroll(function(){ instead of window... but it should work either way.
Here's how I would code this:
$(document).scroll(function() {
var scroll_dst = ($(document).scrollTop());
if (scroll_dst < 200){
nav.css({"position": "relative", "width": "100%", "display": "block"});
}else if((scroll_dst >= 200) && (scroll_dst < 800)) {
nav.fadeOut(500);
}else if((scroll_dst >= 800){
nav.css({"position": "fixed", "width": "100%"}).fadeIn(500);
}
});
You could also make it so when you click the 'go to top' function it automatically places the nav.css back to it's relative state. It's not a perfect solution, but it's better than having no nav at all.
Apparently functions attached to scroll events can be very resource heavy and I think the biggest issue with my code is that the browser couldn't evaluate each of my if statements for every pixel that was scrolled, especially when you scrolled fast to the page top. So I've found a more elegant solution.
In this solution the scroll information is stored in a boolean and he uses a setInterval to check on the scroll position. It's not exactly the same interactivity that I had before, but based on the circumstances it seems the most elegant and resource friendly option. It's actually really pretty code..
You can see it live here.

Change scrollTop offset

I am using bootstrap 3 and have a fullscreen hero unit at the top of my page, below that is my navigation. I have some js which allows my navbar to stick to be fixed at the top after you scroll past the full screen hero. Also some js for my smooth scrolling links.
The problem is the offset is different before you scroll past the full screen hero and after. But it works fine when you are past the jumbotron. I have tried a bunch of different things but I can seem to get this to work exactly.
Check out the fiddle here.
Here is my js for the smooth scrolling links:
$(document).ready(function() {
// navigation click actions
$('.scroll-link').on('click', function(event){
event.preventDefault();
var sectionID = $(this).attr("data-id");
scrollToID('#' + sectionID, 750);
});
// scroll to top action
$('.scroll-top').on('click', function(event) {
event.preventDefault();
$('html, body').animate({scrollTop:0}, 1200);
});
// mobile nav toggle
$('#nav-toggle').on('click', function (event) {
event.preventDefault();
$('#main-nav').toggleClass("open");
});
});
// scroll function
function scrollToID(id, speed){
var offSet = 95;
var targetOffset = $(id).offset().top - offSet;
var mainNav = $('#main-nav');
$('html,body').animate({scrollTop:targetOffset}, speed);
if (mainNav.hasClass("open")) {
mainNav.css("height", "1px").removeClass("in").addClass("collapse");
mainNav.removeClass("open");
}
}
if (typeof console === "undefined") {
console = {
log: function() { }
};
}
By changing var offSet = 95; I am able to adjust the offset but what would be the best way to use 180 before the navbar sticks to the top but 95 when it does?
Also here is the js I am using for my navbar:
$(function () {
/* $(".navbar-fixed-top").css({"top":$(".jumbotron").height()});
$(window).resize(function (e) {
$(".navbar-fixed-top").css({"top":$(".jumbotron").height()});
});*/
$(document).on( 'scroll', function(){
console.log('scroll top : ' + $(window).scrollTop());
if($(window).scrollTop()>=$(".jumbotron").height())
{
$(".navbar").addClass("navbar-fixed-top");
}
if($(window).scrollTop()<$(".jumbotron").height())
{
$(".navbar").removeClass("navbar-fixed-top");
}
});
});
Are you open to angular.js? I have a directive i use for this. As seen here.
I'll grab the plunker link for you. you might find the code helpful.
Essentially you need to create a ghost dom element to take the place of the menu when you pull it to an new layout position.
EDIT: Here it is
I won't suggest grabbing angular just for this. But you can use the basis of the events and logic to build your own solution.
This here is creating an element and placing in its place
$scope.spacer = $element.after(
'<div class="spacer" style="height:' + $element[0].clientHeight + 'px"> </div>').next();
then this element is removed when the menu is back to its static position.
Inspect the dom and watch how it changes, this will probably help you see the events and changes that need to take place.
EDIT 2 SOLUTION:
HERE is the concepts applied to your JSFiddle
It's not the best solution but by adding margin: 0 0 -100px 0; to your .navbaryou lose the spacing issue.
Also you're getting 22 console errors because of missing images. I'm not saying that this is causing any major problems but you would be better off losing them.
The problem is that when you have not scrolled past the hero, navigation is still part of the layout and pushes content bellow it a little lower. When you scroll past (either manually or via a script) the hero, navigation is removed and fix positioned. That makes everything which was bellow to "jump up" exactly of the navigation height.
That means if portfolio was 1000px from the top, on click you say: go 1000px from top; but then porfolio moves 100px up (as explained above) meaning it is now 900px from the top while the window scrolled 1000px as you asked.
When you have scrolled past the hero, nothing changes its position.

Detect Fixed position JavaScript not working in IE

i use YS for fixed position menu, is working fine in firefox but not working in IE.
$(function(){ // this is the shorthand for document.ready
$(document).scroll(function(){ // this is the scroll event for the document
scrolltop = $(document).scrollTop(); // by this we get the value of the scrolltop ie how much scroll has been don by user
if(parseInt(scrolltop) >= 80) // check if the scroll value is equal to the top of navigation
{
$("#navbar").css({"position":"fixed","top":"0"}); // is yes then make the position fixed to top 0
}
else
{
$("#navbar").css({"position":"absolute","top":"80px"}); // if no then make the position to absolute and set it to 80
}
}
}
Any solution fixing this problem for ie?
The problem, to me seems to be that IE doesn't trigger the .scroll event. At least, not in jsfiddle. If you explicitly trigger the event, that does seem to fix things. this fiddle was tested in IE8 and it works. The code:
$(function()
{
$(document).scroll(function()
{//add var here, avoid evil globals:
var scrolltop = $(document).scrollTop();
if(parseInt(scrolltop) >= 80)
{
$("#navbar").css({"position":"fixed","top":"0"});
}
else
{
$("#navbar").css({"position":"absolute","top":"80px"});
}
});//close properly
$(document).scroll();//explicit call
});//close this, too
You are missing ')' in your code working jsfiddle (tested in IE7 and IE9)
$(function(){ // this is the shorthand for document.ready
$(window).scroll(function(){ // this is the scroll event for the document
scrolltop = $(window).scrollTop(); // by this we get the value of the scrolltop ie how much scroll has been don by user
if(parseInt(scrolltop) >= 80) // check if the scroll value is equal to the top of navigation
{
$("#navbar").css({"position":"fixed","top":"0"}); // is yes then make the position fixed to top 0
}
else
{
$("#navbar").css({"position":"absolute","top":"80px"}); // if no then make the position to absolute and set it to 80
}
}); //here
});//here
For position fix must your parent element has this style
position:relative;
best regards

Categories

Resources