Expanding margin with header - javascript

I have a header that when you scroll down it stays in a static flow and goes away. Then when you scroll up the header appears where ever the user is on the page. This all works great, but when I am scrolling all the way up to the top, my margins are expanded due to the header and then once it reaches the very top the margin rise back up to match the header.
I have a banner image with an over-lay. Scroll down a ways and then scroll back up. You will see the changed margin with the image over-lay. Along with that the header is 'fidgety'.
What can I do so the margin always stays the same and doesn't nudge back up?
var didScroll;
var lastScrollTop = 0;
var delta = 5;
var navbarHeight = $('header').outerHeight();
$(window).scroll(function(event){
didScroll = true;
});
setInterval(function() {
if (didScroll) {
hasScrolled();
didScroll = false;
}
}, 250);
function hasScrolled() {
var st = $(this).scrollTop();
// Make sure they scroll more than delta
if(Math.abs(lastScrollTop - st) <= delta)
return;
// If they scrolled down and are past the navbar, add class .nav-up.
// This is necessary so you never see what is "behind" the navbar.
if (st > lastScrollTop && st > navbarHeight){
// Scroll Down
$('header').removeClass('nav-down').addClass('nav-up');
} else {
if (st < navbarHeight) {
if (st === 0 || st < 1) {
$('header').css('position', 'static');
}
} else {
$('header').css('position', 'fixed');
}
// Scroll Up
if(st + $(window).height() < $(document).height()) {
$('header').removeClass('nav-up').addClass('nav-down');
}
}
lastScrollTop = st;
}
<header class="nav-down">
</header>
header {
background: #F2F2F2;
height: 120px;
top: 0;
transition: top 0.5s ease-in-out;
width: 100%;
z-index: 100;
border-bottom: 1px solid #9C9C9C;
}
.nav-up {
top: -123px;
}

This is caused because when you change the position of header to fixed it causes the DOM to be nudged up the same height of header because you're header no longer effect's DOM layout.
The fix:
Would be to append margin-top with the same height of header when you apply position: fixed to your #service-img here it is in code ( Untested since you're using live site ):
function hasScrolled() {
var st = $(this).scrollTop();
// Make sure they scroll more than delta
if (Math.abs(lastScrollTop - st) <= delta)
return;
// If they scrolled down and are past the navbar, add class .nav-up.
// This is necessary so you never see what is "behind" the navbar.
if (st > lastScrollTop && st > navbarHeight) {
// Scroll Down
$('header').removeClass('nav-down').addClass('nav-up');
} else {
if (st < navbarHeight) {
if (st === 0 || st < 1) {
$('header').css('position', 'static');
$('#service-img').css('margin-top', '0px');
}
} else {
$('header').css('position', 'fixed');
$('#service-img').css('margin-top', '120px');
}
// Scroll Up
if (st + $(window).height() < $(document).height()) {
$('header').removeClass('nav-up').addClass('nav-down');
}
}
lastScrollTop = st;
}
EDIT:
Just tested on your site with my code using Chrome DevTools and it works fine. Hope that helped!

Related

Scroll to a position on scroll down and another on scroll up event

I don't know if I'm doing it right but I want to scroll to the next div when the user scroll down and scroll to the previous div in the page when the user scroll up.
First of all I do this to test the scroll event and the animation of scrolling :
$(document).ready(function() {
$(window).scroll(function(){
$("html, body").animate({
scrollTop: 1000
}, 1000);
});
});
That's just a test but it work well.
Now, I want to differentiate the scroll down and the scroll up event to scroll to the next or the previous div so I search and I found some solutions like this :
$(document).ready(function() {
var lastPosition = $(window).scrollTop();
$(window).scroll(function(){
var newPosition = $(window).scrollTop();
if(lastPosition - newPosition > 0){
$("html, body").animate({
scrollTop: 1000
}, 1000);
}
else {
$("html, body").animate({
scrollTop: 0
}, 1000);
}
});
});
But it doesn't work...
I think the method to get the scroll down or the scroll up doesn't work in my case.
Do you have any solution to do this or maybe an alternative ?
Thank you.
In your case, the height of the body or your container should be set to the window height and the overflow of that should be set to hidden, because you want to scroll to the target Div by javascript.
by setting the overflow: hidden on the body or your container, you prevent
the window from scrolling on the page.
body {
background: #eee;
height: 100%;
overflow: hidden;
}
The next step is detecting the scrolling direction (Up/Down). You can
check it by the deltaY property of the scroll event.
Finally, get the next or previous Div and scroll to it.
The complete example is here
$(window).on('mousewheel DOMMouseScroll', function(event) {
var deltaY = event.originalEvent.deltaY || event.deltaY;
if (deltaY > 0) {
// Scrolled to Down: Next Div
} else if (deltaY < 0) {
// Scrolled to Up: Previous Div
}
});
You can see the completed code here:
<html>
<head>
<script src="https://code.jquery.com/jquery-3.4.1.min.js" type="text/javascript"></script>
<style type="text/css">
body {
background: #eee;
height: 100%;
overflow: hidden;
}
.section {
height: 600px;
}
.section.active {
background: #ccc;
}
</style>
</head>
<body>
<div class="active section">Section 1</div>
<div class="section">Section 2</div>
<div class="section">Section 3</div>
<script type="text/javascript">
$(window).on('mousewheel DOMMouseScroll',function(event) {
var deltaY = event.originalEvent.deltaY || event.deltaY,
$activeSection = $('.section.active'),
$container = $('body'),
containerOffset = $container[0].offsetTop,
$targetSection = null,
mustBeScroll = false;
if(deltaY > 0) { // Scrolled to Down: Next Div
if($activeSection.next('.section').length > 0) {
$targetSection = $activeSection.next('.section');
mustBeScroll = true;
}
} else if (deltaY < 0) { // Scrolled to Up: Previous Div
if ($activeSection.prev('.section').length > 0) {
$targetSection = $activeSection.prev('.section');
mustBeScroll = true;
}
}
if(mustBeScroll == true) {
$container.stop(false, true).animate({ scrollTop : $targetSection[0].offsetTop - containerOffset }, 500);
// Change background color
$activeSection.removeClass('active');
$targetSection.addClass('active');
}
});
</script>
</body>
</html>

Adding a class between when user scrolls between 200px and 300px only

I'm trying to add a class to div when a user scrolls down the page. When they scroll 200px down the page I want a class to be added and then once the user scrolls down 300px I want the class to be removed. Similarly, when the user scrolls back up the page and is 300px from the top, I then want the class to be added until it gets to 200px and then removes the class.
I've tried so many variations but I think I'm approaching it all wrong. Here's a jsfiddle of how far I've gotten so far - http://jsfiddle.net/v8my3sr1/
$(window).on('scroll',function() {
var scroll = $(window).scrollTop();
if (scroll >= 200) {
$(".trigger").addClass("wow");
} else {
$(".trigger").removeClass("wow");
}
});
You condition is incorrect. You should check that scroll value is between 200 and 300
$(window).on('scroll',function() {
var scroll = $(window).scrollTop();
if (300 >= scroll && scroll >= 200) {
$(".trigger").addClass("wow");
} else {
$(".trigger").removeClass("wow");
}
});
$(window).on('scroll',function() {
var scroll = $(window).scrollTop();
if (300 >= scroll && scroll >= 200) {
$(".trigger").addClass("wow");
} else {
$(".trigger").removeClass("wow");
}
});
.container {
height: 2000px;
}
.trigger {
margin-top: 300px;
height: 400px;
}
.wow {
background: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="trigger">
<h1>Trigger container</h1>
</div>
</div>
Also you can use .toggleClass() to simplifying code
$(window).on('scroll',function() {
var scroll = $(window).scrollTop();
$(".trigger").toggleClass("wow", 300 >= scroll && scroll >= 200);
});
Try something like this :
$(window).scroll(function(){
var cutoff = $(window).scrollTop();
$(".trigger").each(function(){
if($(this).offset().top + $(this).height() > cutoff){
panel.removeClass('wow');
$(this).addClass('wow');
return false;
}
})
})

How to make a semi-sticky header?

I have a header that starts in the middle of the page.
I'd like for it to move up and past the top of the page on scroll down (with ease-out) and then come back and stay on top of the page on scroll up until the user is back to the main page, at which point the head comes back to the middle.
As of right now, i just have it ease-in to the top and stay there with:
<script>
window.onscroll = function() {myFunction()};
var header = document.getElementById("myHeader");
var sticky = header.offsetTop;
function myFunction() {
if (window.pageYOffset >= sticky-180) {
header.classList.add("sticky");
} else {
header.classList.remove("sticky");
}
}
</script>
css:
.sticky {
position: fixed;
top: 0;
width: 100%;
transition: all 0.4s ease;
}
i didn't make the ease-in animation, so I'm not entirely sure how it works. But I just have it in the column class which has the scrolling animation applied to it, so it seems to work:
$(document).ready(function() {
let speeds = {
'slow': 0.5,
'mid': 0.7,
'fast': 1,
'ss':1.75,
};
let noColumns = $('.column').length;
let columns = new Array();
for (let i = 0; i < noColumns; i++) {
columns.push({
columnHeight: parseInt($('.column').eq(i).css('height')),
position: 0,
speed: speeds[$('.column').eq(i).attr('data-speed')]
});
}
let previousScroll = $(this).scrollTop();
var conHeight = parseInt($('.column').eq(0).css('height')) * 3;
//all activate. the times x makes it keep going after we run out of original view
$('.tall').css('height', conHeight + 'px');
$(window).on('scroll', function(event) {
var shift = $(this).scrollTop() - previousScroll;
previousScroll = $(this).scrollTop();
for (var i = 0; i < noColumns; i++) {
columns[i].position -= shift * columns[i].speed;
$('.column').eq(i).css('top', columns[i].position + 'px');
}
});
});
i found a couple of tutorials on how to make a header that disappears on the top and then comes back when you scroll up, like this one https://codepen.io/kaemak/pen/mHyKa/, but I'm not sure how to combine it with what I have already.

Code not working correctly in Safari and responsive browsers

I have the following code which 'shows/hides' my navigation up off the top of the screen, and brings it down again.
jQuery(document).ready(function($){
var didScroll;
var lastScrollTop = 0;
var delta = 5;
var navbarHeight = $('nav').outerHeight(true);
$(window).scroll(function(event) { didScroll = true; });
setInterval(function() {
if (didScroll) {
hasScrolled();
didScroll = false;
}
}, 0);
function hasScrolled() {
if($( window ).width() > 768) {
var st = $(this).scrollTop();
if (Math.abs(lastScrollTop - st) <= delta)
return;
if (st > lastScrollTop) {
// Scroll Down
$('#screen-nav').removeClass('nav-down').addClass('nav-up');
} else {
$('#screen-nav').removeClass('nav-up').addClass('nav-down');
}
}
lastScrollTop = st;
}
});
css
#screen-nav {
position: fixed;
top: 0; left: 0; right: 0;
}
#screen-nav.nav-up { top: -100px; }
#screen-nav.nav-down { top: 0; }
The problem is that on the safari browser and when the screen changes from mobile size (<768px on all browsers) to screen size sometimes the .nav-up class gets added and the navigation doesn't show. But only when the user scrolls to the top of the page.
Not sure if there is a better way to write the code to ensure proper functionality.
I see you are using this example. He has the fiddle working well too. the only thing is that on browser resize nothing regarding show the nav is in place. You should be able to just add that separately.
$(window).resize(function(){
$('#screen-nav').removeClass('nav-up').addClass('nav-down')
});
I updated his original fiddle to reflect the addition of window resize handling.

Applying a third condition to function

I have the following function which appliess css to #screen-nav when the user scrolls up and different css when user scrolls down
jQuery(document).ready(function($){
var didScroll;
var lastScrollTop = 0;
var delta = 5;
var navbarHeight = $('nav').outerHeight(true);
$(window).scroll(function(event) { didScroll = true; });
setInterval(function() {
if (didScroll) {
hasScrolled();
didScroll = false;
}
}, 0);
function hasScrolled() {
if($( window ).width() > 768) {
var st = $(this).scrollTop();
if (Math.abs(lastScrollTop - st) <= delta)
return;
if (st > lastScrollTop) {
// Scroll Down
$('#screen-nav').removeClass('nav-down').addClass('nav-up');
} else {
$('#screen-nav').removeClass('nav-up').addClass('nav-down');
}
}
lastScrollTop = st;
}
});
css
#screen-nav {
position: fixed;
top: 0; left: 0; right: 0;
}
#screen-nav.nav-up { top: -100px; }
#screen-nav.nav-down { top: 0; }
I want to add a third class. I want #screen-nav { top: 50px; } when the user is 300px from the top. (so I figure apply a third class .nav-top when the user is in that position) But not sure how to integrate it into my code.
Basically, I want the nav (navigation) to appear lower on the page when the user is at the top, and when it comes down when the user scrolls up, I want it to be right at the top.
add condition of javascript
if(st == 300){ $("#screen-nav").css({ top: '50px' }); }
<script type="text/javascript">
jQuery(document).ready(function($){
var didScroll;
var lastScrollTop = 0;
var delta = 5;
var navbarHeight = $('nav').outerHeight(true);
$(window).scroll(function(event) { didScroll = true; });
setInterval(function() {
if (didScroll) {
hasScrolled();
didScroll = false;
}
}, 0);
function hasScrolled() {
if($( window ).width() > 768) {
var st = $(this).scrollTop();
if (Math.abs(lastScrollTop - st) <= delta)
return;
if(st == 300)
{
$("#screen-nav").css({ top: '50px' });
}
else if (st > lastScrollTop) {
// Scroll Down
$('#screen-nav').removeClass('nav-down').addClass('nav-up');
}
else {
$('#screen-nav').removeClass('nav-up').addClass('nav-down');
}
}
lastScrollTop = st;
}
});
</script>

Categories

Resources