I have the following code which adds/removes a class to my navigation div when the user scrolls.
setInterval(function() {
if (didScroll) {
hasScrolled();
didScroll = false;
}
}, 100);
function hasScrolled() {
if ($(window).width() > 768) {
var st = $(this).scrollTop();
if (Math.abs(lastScrollTop - st) <= delta) {
return;
}
if (st > lastScrollTop && lastScrollTop >= 0 && st > 0) {
$('#anim-nav').removeClass('nav-down').addClass('nav-up');
} else {
$('#anim-nav').removeClass('nav-up').addClass('nav-down');
}
}
lastScrollTop = st;
}
});
I want to add .trans-bg to #anim-nav when the user is close to the top of the screen. It has a background of white, but when it gets to the top o the screen I want it transparent as it goes over an image. However when i added it to this function wasn't reliable. Sometimes it would stay transparent, or not turn transparent.
Not sure how to add something that constantly runs to make sure if the user is near/at the top it applies.
Maybe this can help?
$(window).on('scroll', function () {
if ($(window).scrollTop() > 10) {
$('body').addClass('scrolled');
} else {
$('body').removeClass('scrolled');
}
});
body {
background: url("https://www.toptal.com/designers/subtlepatterns/patterns/christmas-black.png");
height: 3000px;
}
.scrolled .header {
background-color: rgba(255, 255, 255, .8)
}
.header {
background-color: #fff;
height: 80px;
position: fixed;
left: 0;
top: 0;
right: 0;
transition: .2s;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<header class="header"></header>
Solution: Listen to scroll changes instead of checking for scrolls at a interval.
Example of listening to scroll at top using javaScript:
window.addEventListener('scroll', function(e) {
if (document.body.scrollTop == 0) {
alert("top");
}
});
Related
This code in my CodePen works to change the height of my div.box when I scroll down. It also works when I reverse scroll (scroll back up). When I reach the top of the window, it doesn't seem to work. Do you know what's wrong with my code when the window reaches the top, or what to add to make it work in all of these 3 cases?
Here is the full CodePen so you can see what I mean: https://codepen.io/celli/pen/LYNYNQq
gsap.set(".box", {
transformOrigin: "top left"
});
var lastScrollTop = 0;
window.addEventListener("scroll", function() {
var st = window.pageYOffset || document.documentElement.scrollTop;
if (st > lastScrollTop) {
// down-scroll code
gsap.to(".box", {
scaleY: .2
})
} else if (st < lastScrollTop) {
// up-scroll code
gsap.to(".box", {
scaleY: .5
})
} else if (window.pageYOffset == 0) {
// when the window reaches the top
gsap.to(".box", {
scaleY: 1
})
}
lastScrollTop = st <= 0 ? 0 : st; // For Mobile or negative scrolling
}, false);
/*
gsap.to(".box", {
scaleY:1,
ease: "circ:out",
scrollTrigger: {
trigger: ".box",
markers:true,
start: "top top",
toggleActions:"play none none reverse"
},
});
*/
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.box {
width: 100%;
height: 200px;
background-color: aqua;
opacity: .5;
position: fixed;
}
.sp {
height: 1000px;
width: 100%;
background-color: #cccccc;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.4.2/gsap.min.js"></script>
<script src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/16327/ScrollTrigger.min.js"></script>
<div class="box"></div>
<div class="sp"></div>
You need to check the most specific conditions first; in this case, you should check if the y-position is 0 first, as that will also be covered by checking if the current position is less than the previous condition.
if(st === 0){
// when the window reaches the top
gsap.to(".box", {
scaleY: 1
})
} else if (st > lastScrollTop) {
// down-scroll code
gsap.to(".box", {
scaleY: .2
})
} else if (st < lastScrollTop) {
// up-scroll code
gsap.to(".box", {
scaleY: .5
})
}
gsap.set(".box", {
transformOrigin: "top left"
});
var lastScrollTop = 0;
window.addEventListener("scroll", function() {
var st = window.pageYOffset || document.documentElement.scrollTop;
if(st === 0){
// when the window reaches the top
gsap.to(".box", {
scaleY: 1
})
} else if (st > lastScrollTop) {
// down-scroll code
gsap.to(".box", {
scaleY: .2
})
} else if (st < lastScrollTop) {
// up-scroll code
gsap.to(".box", {
scaleY: .5
})
}
lastScrollTop = st <= 0 ? 0 : st; // For Mobile or negative scrolling
}, false);
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.box {
width: 100%;
height: 200px;
background-color: aqua;
opacity: .5;
position: fixed;
}
.sp {
height: 1000px;
width: 100%;
background-color: #cccccc;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.4.2/gsap.min.js"></script>
<script src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/16327/ScrollTrigger.min.js"></script>
<div class="box"></div>
<div class="sp"></div>
I'm creating a header which:
Displays on default (transparent background)
When user scrolls down the page (25px), it will add the header--maroon class to header - which it does. The header-maroon class basically adds the background color and anchor styles.
But at this point (when the user has scrolled 25px down the page), I want the header to "fade up" smoothly and basically stay hidden when the user is scrolling down.
Lastly, when a user scrolls (10px) up the page, I want the header to fade in neatly at the top of the viewpoint.
Here's my current approach. It kind of works, but not as smooth as I'd like (as in the the header just appears, I want it to transition in). I have tried to add transitions, but it doesn't work?
/**********/
/* SCROLL */
/**********/
//Add transition when scrolling down
$(window).scroll(function() {
var scroll = $(window).scrollTop();
if (scroll >= 25) {
$("header").addClass("header--maroon");
} else {
$("header").removeClass("header--maroon");
}
});
// add scroll effect on page refresh too
$(function() {
var scroll = $(window).scrollTop();
if (scroll >= 10) {
$(".mainMenu").addClass("header--maroon");
} else {
$(".mainMenu").removeClass("header--maroon");
}
});
/******************************/
/* HIDE HEADER ON SCROLL DOWN */
/******************************/
var didScroll;
var lastScrollTop = 0;
var delta = 25;
var navbarHeight = $('header').outerHeight();
$(window).scroll(function(event){
didScroll = true;
});
setInterval(function() {
if (didScroll) {
hasScrolled();
didScroll = false;
}
}, 250);
function hasScrolled() {
var st = $(this).scrollTop();
if(Math.abs(lastScrollTop - st) <= delta)
return;
if (st > lastScrollTop && st > navbarHeight){
// Scroll Down
$('header').removeClass('nav-down').addClass('nav-up');
} else {
// Scroll Up
if(st + $(window).height() < $(document).height()) {
$('header').removeClass('nav-up').addClass('nav-down');
}
}
lastScrollTop = st;
}
body{
background: wheat;
height:1000px;
}
header {
position: fixed;
transition: top 0.2s ease-in-out;
width: 100%;
height: 90px;
background: transparent;
}
.nav-up {
top: -90px;
transition: top 0.2s ease-in-out;
}
.header--maroon {
background: #521717;
transition: top 0.2s ease-in-out;
}
.mainMenu {
background-color: transparent;
width: 100%;
padding: 10px 0px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<header class="nav-down">
<div class="mainMenu">Link</div>
</header>
<div class="gap"></div>
Try implementing this:
JSFiddle
HTML:
<header class="nav-down">
This is your menu.
</header>
<main>
This is your body.
</main>
<footer>
This is your footer.
</footer>
CSS:
body {
padding-top: 40px;
}
header {
background: #f5b335;
height: 40px;
position: fixed;
top: 0;
transition: top 0.2s ease-in-out;
width: 100%;
}
.nav-up {
top: -40px;
}
main {
background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAPklEQVQYV2O8dOnSfwYg0NPTYwTRuAAj0QqxmYBNM1briFaIzRbi3UiRZ75uNgUHGbfvabgfsHqGaIXYPAMAD8wgC/DOrZ4AAAAASUVORK5CYII=) repeat;
height: 2000px;
}
footer { background: #ddd;}
* { color: transparent}
JS:
// Hide Header on on scroll down
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 {
// Scroll Up
if(st + $(window).height() < $(document).height()) {
$('header').removeClass('nav-up').addClass('nav-down');
}
}
lastScrollTop = st;
}
(** Credit for this code goes to the creator of the JSFiddle)
Hope this helps!
You can use the .animate() class.
Replace...
$('header').removeClass('nav-down').addClass('nav-up');
With...
$("header").animate({ top: '-90px' },300);
And replace...
$('header').removeClass('nav-up').addClass('nav-down');
With...
$("header").animate({ top: '10px' },300);
Here is a JSFiddle example using your code.
Note that this is just a rough implementation.
You can play with it and tweak it until it works as you want it to.
Add transition to the class which you are adding on scroll.
.header-maroon{
transition: all 0.5s ease-in-out;
}
How can I make the navigation bar re-appear only when the users scrolls at the very top? currently, the nav bar appears when the users scrolls up, irrelevant the position of the screen.
Html
<header class="nav-down">
<div> navigation </div>
</header>
Javascript
var didScroll;
var lastScrollTop = 0;
var delta = 5;
var navbarHeight = $('#navigation-container').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('navigation-container').addClass('nav-up');
} else {
// Scroll Up
if(st + $(window).height() < $(document).height()) {
$('header').removeClass('nav-up').addClass('nav-down');
}
}
lastScrollTop = st;
}
CSS
header {
height: 40px;
position: fixed;
top: 0;
transition: top 0.5s ease-in-out;
width: 100%;
z-index: 999;
padding-top: 50px;
}
.nav-up {
top: -70px;
}
Thanks!
There are two things you need to do in order to achieve that:
Delete / comment the entire navbar script.
Cleanup the header declaration in CSS by removing all but the following 2 lines:
header {
height: 40px;
width: 100%;
}
I'm currently swapping a logo for smaller logo when the user scrolls down the page. At the moment it's a straight swap. However I'd like to add a nice animated fade in/out so the larger logo fades out, smaller logo fades in and vice-versa.
Here's a pen of my current attempt: http://codepen.io/abbasinho/pen/yyomrB
I've tried to adding fadeIn but with not joy.
JS:
$(function() {
var logo = $(".lrg-logo");
$(window).scroll(function() {
var scroll = $(window).scrollTop();
if (scroll >= 500) {
logo.removeClass('lrg-logo').addClass("sml-logo").fadeIn( "slow");
} else {
logo.removeClass("sml-logo").addClass('lrg-logo').fadeIn( "slow");
}
});
});
CSS:
.wrapper {
height: 2000px;
position: relative;
background: green;
}
header {
position: fixed;
width: 100%;
height: 50px;
background: grey;
}
.lrg-logo {
width: 300px;
height: 50px;
text-align: center;
background: red;
}
.sml-logo {
width: 200px;
height: 20px;
text-align: center;
background: red;
}
2 things:
logo must first be hidden in order to fade it in.
fade should not happen on every scroll event, but just once when scrolltop > 500
$(function() {
var logo = $(".lrg-logo");
$(window).scroll(function() {
var scroll = $(window).scrollTop();
if (scroll >= 500) {
if(!logo.hasClass("sml-logo")) {
logo.hide();
logo.removeClass('lrg-logo').addClass("sml-logo").fadeIn( "slow");
}
} else {
if(!logo.hasClass("lrg-logo")) {
logo.hide();
logo.removeClass("sml-logo").addClass('lrg-logo').fadeIn( "slow");
}
}
});
});
Use this
$(function() {
var logo = $(".lrg-logo");
var scrolling = false;
var small = false;
$(window).scroll(function() {
var scroll = $(window).scrollTop();
if (scroll >= 500 && !scrolling && !small) {
scrolling = true;
logo.fadeOut(300);
window.setTimeout(function() {
logo.fadeIn( 300).removeClass('lrg-logo').addClass("sml-logo");
scrolling = false;
small = true;
}, 300);
} else if(!scrolling && small) {
scrolling = true;
logo.fadeOut( 300);
window.setTimeout(function() {
logo.fadeIn( 300).removeClass('sml-logo').addClass("lrg-logo");
scrolling = false;
small = false;
}, 300);
}
});
});
I have two flags. One to see if its currently animating or not. Another one to check if its small or large.
http://codepen.io/anon/pen/jEGNbN
the code is in the link above
I have a nav bar that is fixed to the top of the page when the width is under 768px.
When it is over 768px it starts at the bottom and when the user scroll past it it become stuck to the top.
Both of these instance work fine on their own, but when the browser is resized there are some issues when going from under 768px to above. (Going from 768 to below works fine.)
When I load the page in a browser size under 768px and then resize the window above that is where I run in to problems.
I would like for the nav bar to smoothly transition between states. (It works beautifuly when loading above 768px then reszing to under and reszing above - Ideally this is how I would like it to work when loaded below 768px.) Or as an alternative just have the nav bar be fixed to the top when moving from under 768px to above.
This is the link to the site.
This is my CSS
.header{
width: 100%;
min-width: 300px;
height: 100px;
padding: 0px;
background: black;
position: absolute;
bottom: 0px;
z-index: 99999;
-webkit-font-smoothing: subpixel-antialiased;
}
.header.fixed{
width: 100%;
position: fixed;
top: 0px;
height: 100px;
-webkit-font-smoothing: subpixel-antialiased;
}
#media only screen and (max-width: 768px){
.header{
width: 100%;
background: black;
position: fixed;
top: 0px;
height: 100px;
-webkit-font-smoothing: subpixel-antialiased;
}
}
and this is the Javascript
<script>
jQuery(document).ready(function() {
var s = jQuery(".header");
var pos = s.position();
jQuery(window).scroll(function() {
var windowpos = jQuery(window).scrollTop();
if (windowpos >= pos.top) {
s.addClass("fixed");
} else {
s.removeClass("fixed");
}
});
});
</script>
I have also tried below to no luck.
<script>
if ( jQuery(window).width() > 768) {
jQuery(document).ready(function() {
var s = jQuery(".header");
var pos = s.position();
jQuery(window).scroll(function() {
var windowpos = jQuery(window).scrollTop();
if (windowpos >= pos.top) {
s.addClass("fixed");
} else {
s.removeClass("fixed");
}
});
});
}</script>
<script>
jQuery(window).resize(function(){
if ( jQuery(window).width() > 768) {
jQuery(document).ready(function() {
var s = jQuery(".header");
var pos = s.position();
jQuery(window).scroll(function() {
var windowpos = jQuery(window).scrollTop();
if (windowpos >= pos.top) {
s.addClass("fixed");
} else {
s.removeClass("fixed");
}
});
});
}})</script>
try this:
function sticky_navigation() {
var browserWidth = $(window).width();
var scroll_top = $(window).scrollTop(); // our current vertical position from the top
// if we've scrolled more than the page, change its position to fixed to stick to top,
// otherwise change it back to relative
if ((scroll_top > $('.header').height()) && (browserWidth > 720)) {
$('.header').css({ 'position': 'fixed', 'top':0, 'z-index':999999, 'opacity': 0.9, 'box-shadow': '0px 3px 5px #393939' });
} else {
$('.header').css({ 'position': 'relative', 'opacity': 1, 'box-shadow': 'none' });
}
};
// and run it again every time you scroll
$(window).scroll(function() {
sticky_navigation();
});
// and run every time you resize to boot
$(window).resize(function() {
sticky_navigation();
});