Hide menu on scroll down and show on scroll up - javascript

I made this snippet code to hide menu on scroll down and show on scroll up but I have some issues, when I scroll to top the menu still have fixed position, how I can resolve this problem, Thanks!
JAVSCRIPT :
$(window).bind('scroll', function () {
if ($(window).scrollTop() > 500) {
$('.mainmenu').addClass('nav-down');
}
});
// Hide Header on on scroll down
var didScroll;
var lastScrollTop = 0;
var delta = 5;
var navbarHeight = $('.mainmenu').outerHeight();
$(window).scroll(function(event){
didScroll = true;
});
setInterval(function() {
if (didScroll) {
hasScrolled();
didScroll = false;
}
}, 500);
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
$('.mainmenu').removeClass('nav-down').addClass('nav-up');
} else {
// Scroll Up
if(st + $(window).height() < $(document).height()) {
$('.mainmenu').removeClass('nav-up');
}
}
lastScrollTop = st;
}
CSS :
.mainmenu {
background: #222;
height: 50px;
padding: 0 15px;
width: 80%;
margin: 0 auto;
}
.nav-down{
position: fixed;
top: 0;
transition: top 0.2s ease-in-out;
width: 100%;
}
.nav-up {
top: -50px;
}
Demo : jsfiddle

To you first listener, just add an else statement as follows:
$(window).bind('scroll', function () {
if ($(window).scrollTop() > 150)
$('.mainmenu').addClass('nav-down');
else
$('.mainmenu').removeClass('nav-down');
});
Also note that you don't need a setInterval() for the second listener, see jsfiddle

I tested it and it works fine!!
$(window).bind('scroll', function () {
if ($(window).scrollTop() > 500) {
$('.mainmenu').addClass('nav-down');
}
else
{
$('.mainmenu').removeClass('nav-down');
}
});

Add an else to your scrollTop with a removeClass and you should be fine, I tested it and it works. Here
$(window).bind('scroll', function () {
if ($(window).scrollTop() > 500) {
$('.mainmenu').addClass('nav-down');
}
else
{
$('.mainmenu').removeClass('nav-down');
}
});

Detect nav direction with a variable
var lastscrolltop=0;
jQuery(window).bind('scroll', function () {
if (jQuery(window).scrollTop() > lastscrolltop)
jQuery('.mainmenu').addClass('nav-up');
else
jQuery('.mainmenu').removeClass('nav-up');
lastscrolltop=jQuery(window).scrollTop();
});
and use css transition for a smooth show/hide
.mainmenu {
transition:all 0.5s ;
}

Your way is too much complicated.
You can hide the menu on scroll with a simple transition using jQuery .fadeIn() and fadeOut(), without the need for css.
var lastScrollTop = 0;
$(window).scroll(function(event){
var st = $(this).scrollTop();
if (st > lastScrollTop){
$('.mainmenu').fadeOut('fast');
} else {
$('.mainmenu').fadeIn('fast');
}
lastScrollTop = st;
});

Related

Class not always applied when user is at top of the page

I am using the following code to apply different classes to #nav depending if the user scrolls UP, DOWN, or is at the top of the page.
.nav-down applied when user scrolls up
.nav-up applied when user scrolls down
.nav-down-top when user scrolls to the top of the page
code
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;
}
}, 100);
function hasScrolled() {
if($( window ).width() > 768) {
var st = $(this).scrollTop();
if (Math.abs(lastScrollTop - st) <= delta)
return;
if (st > lastScrollTop) {
// Scroll Down
$('#s-nav').removeClass('nav-down').removeClass('nav-down-top').addClass('nav-up');
} else {
// Scroll Up (# top of screen)
if (st === 0) {
$('#s-nav').removeClass('nav-up').removeClass('nav-down').addClass('nav-down-top');
} else { //if (st + $(window).height() < $(document).height()) {
$('#s-nav').removeClass('nav-up').removeClass('nav-down-top').addClass('nav-down');
}
}
}
lastScrollTop = st;
}
});
The problem is that when the user is at the top of the page or scrolls to the top .nav-down-top doesn't always get applied. This often happens when the user doesn't scroll very far to get to the top. I'm not sure how to ensure that .nav-down-top is applied when the user is at the top of the page.
$(function(){
var shrinkHeader = 300;
$(window).scroll(function() {
var scroll = getCurrentScroll();
if ( scroll >= shrinkHeader ) {
$('.navbar-fixed').addClass('class');
}
else {
$('.navbar-fixed').removeClass('oneclass');
$('.navbar-fixed').addClass('otherclass');
}
});
function getCurrentScroll() {
return window.pageYOffset || document.documentElement.scrollTop;
}
});
Try this script cleaner and tell me if it worked
What you seem to want is this:
var el = $('#test1')
$(window).scroll(function(){
if($(window).scrollTop() > 50){
console.log("addClass")
$(el).addClass('slideUp');
} else {
console.log("removeClass")
$(el).removeClass('slideUp');
}
})
https://jsfiddle.net/m0nz41ep/1/
You do not need to set an interval for the window to check the information, since the scroll is already an event that checks the window whenever you input information. :)
Also, are you doing animations?
You need to tell the CSS file that the divs you want to manipulate will be animated.
-webkit-transition: all 1s; // Chrome
-moz-transition: all 1s; // Mozilla
-o-transition: all 1s; // Opera
transition: all 1s;
If it's just one div add it to the id for the div, if it's multiple, add it to a class and add the class to all of the divs. The rest of the code should do the magic!

How can I create a hide on scroll down and show on scroll up menu whitout jquery or other dependencies

I am working on a website that needs to be fast and light.
I used this script before on other websites but with jquery library.
For this specific website I need to run very fast since most of the users have low mobile internet speed.
For this reason I want just plain javascript to do this task.
I'm not very familiar with javascript so I need some help that's why I'm asking for.
Can anyone help me whit this please?
Thank you,
John
// 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;
}
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}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<header class="nav-down">
This is your menu.
</header>
<main>
This is your body.
</main>
<footer>
This is your footer.
</footer>
You can use this:
var mousewheelevt = (/Firefox/i.test(navigator.userAgent)) ? "DOMMouseScroll" : "mousewheel" //FF doesn't recognize mousewheel as of FF3.x
window.addEventListener(mousewheelevt, function(e){
var evt = window.event || e //equalize event object
evt = evt.originalEvent ? evt.originalEvent : evt; //convert to originalEvent if possible
var delta = evt.detail ? evt.detail*(-40) : evt.wheelDelta //check for detail first, because it is used by Opera and FF
if(delta > 0) {
document.getElementById('menu').style.display = "block";
}
else{
if(window.pageYOffset > 250)
document.getElementById('menu').style.display = "none";
}
});

condensing code/script in head tags

I have 3 scripts hard-coded in my head tags which all target different elements in my site. However most of them are based on similar events (when mouse scrolls, etc) I am wondering if it could be combined/condensed at all. I've tried but can't seem to make it any smaller while keeping functionality.
script 1 - animates #nav away when user scrolls dwn, brings it back when scrolled up
script 2 - animates away a second menu (#nav-BN) on < 768px screens when user scrolls up or down
script 3 - hides and shows a div/button > 768px screens, hides it if smaller
<script>
var didScroll;
var lastScrollTop = 0;
var delta = 5;
var navbarHeight = $('nav').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
$('#s-nav').removeClass('nav-down').addClass('nav-up');
} else {
// Scroll Up
if (st + $(window).height() < $(document).height()) {
$('#s-nav').removeClass('nav-up').addClass('nav-down');
}
}
lastScrollTop = st;
}
</script>
<script>
var lastPos=0;
$(window).scroll(function(event) {
if (window.innerWidth < 768) {
$('#nav-BN').addClass('BN-nav-hide').removeClass('BN-nav-show');
clearTimeout($.data(this, 'scrollTimer'));
$.data(this, 'scrollTimer', setTimeout(function() {
$('#nav-BN').addClass('BN-nav-show').removeClass('BN-nav-hide');
}, 250));
}
});
</script>
<script>
$(window).scroll(function () {
if (window.innerWidth > 768) {
if ($(window).scrollTop() + $(window).height() > ($(document).height() - 200)) {
$("#up-btn").fadeIn(500);
} else {
$("#up-btn").fadeOut(500);
}
} else {
$("#up-btn").fadeOut(250);
}
});
</script>
you might notice some important things:
Replace multiple jQuery search by storing the objects in variables
Is not necessary to have two classes for hidden and shown, you can have one class named 'active' instead of BN-nav-show, and in case that class is missing it should be NB-nav-hide
if (window.innerWidth > 768) and (window.innerWidth < 768) can be merged into one unique structure:
if(){
} else {
}
This should help
<script>
var didScroll;
var lastScrollTop = 0;
var delta = 5;
var navbarHeight = $('nav').outerHeight();
var $window = $(window);
var $upBtn = $("#up-btn")
var lastPos=0;
window.scroll(function(event) {
didScroll = true;
var $navBN = $('#nav-BN');
if (window.innerWidth > 768) {
if ($window.scrollTop() + window .height() > ($(document).height() - 200)) {
upBtn.fadeIn(500);
} else {
upBtn.fadeOut(500);
}
} else {
navBN.removeClass('active');
clearTimeout($.data(this, 'scrollTimer'));
$.data(this, 'scrollTimer', setTimeout(function() {
navBN.addClass('active');
}, 250));
upBtn.fadeOut(250);
}
});
function hasScrolled() {
var st = $(this).scrollTop();
if (Math.abs(lastScrollTop - st) <= delta) return;
if (st > lastScrollTop && st > navbarHeight ) {
// Scroll Down
$('#s-nav').removeClass('nav-down').addClass('nav-up');
} else {
// Scroll Up
if (st + $(window).height() < $(document).height()) {
$('#s-nav').removeClass('nav-up').addClass('nav-down');
}
}
lastScrollTop = st;
}
setInterval(function() {
if (didScroll) {
hasScrolled();
didScroll = false;
}
}, 250);
</script>
If you don't have a problem with toggle classes, then you can do that
https://jsfiddle.net/9yhug2qg/1/
var windowST, navBar, navBarHeight;
$(window).on('scroll', function () {
windowST = $(window).scrollTop();
navBar = $('.navbar');
navBarHeight = parseInt(navBar.height());
if (windowST > navBarHeight) {
$(navBar).addClass('out-of-area');
} else {
$(navBar).removeClass("out-of-area");
}
});
* { margin: 0;padding: 0; }
body { height: 700vh; }
.navbar {
position: fixed;
width: calc(100%);
height: 70px;
background-color: #0ff;
color: #fff;
transition: all 1s ease
}
ul {
position: absolute;
top: 50%;
transform: translateY(-50%);
visibility: visible;
width:calc(100% - 60px);
height: 60px;
background-color: #fff;
}
.navbar.out-of-area {
transform: translateY(-100px);
}
.navbar > .nav_btn {
position: absolute;
width: 40px;
height: 40px;
background-color: #151515;
right: 4px;
top: 50%;
transform: translateY(-50%);
cursor: pointer;
visibility: hidden;
}
#media only screen and (max-width: 768px) {
.navbar > .nav_btn { visibility: visible; }
ul { visibility: hidden; }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<nav class="navbar">
<nav class="nav_btn"></nav>
<ul></ul>
</nav>
</div>

Header hiding on scroll positioning

I have included a snippet to show the general idea of what I have right now. The snippet will show a header and if you scroll the header stays the same size until the full height of the header has been scrolled down and then it will go away. Then when you scroll up (when the header gone) the header will show.
The issue I cannot seem to figure out is how to remove the position: fixed from my css and still get the javascript to work. I want the header to scroll down normally (just like Stack overflow's header), however with the ability to still re-appear when scrolling up.
I tried taking out position: fixed and the script broke. I also tried adding position: fixed to the nav-up class...neither change worked.
Does anyone know what I could do to make this work?
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;
}
html, body {
padding:0;
margin:0;
}
header {
/*background: #2F4F4F;*/
/*background: #53868B;*/
/*background: #35586C;*/
background: #F2F2F2;
height: 120px;
position: fixed;
top: 0;
transition: top 0.2s ease-in-out;
width: 100%;
z-index: 100;
}
.nav-up {
top: -120px;
}
#logo {
padding: 5px 20%;
display: inline-block;
}
#logo img {
height: 110px;
width: auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<header class="nav-down">
<div id="logo">
<img src="images/eslich.png" alt="">
</div>
</header>
<br><br><Br><br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><Br><br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><Br><br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><Br><br><br><br><br><br><br><br><br><br><br><br><br>
Update
This is the new jsfiddle using her code https://jsfiddle.net/jz8aa5yz/2/
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 < 50) {
$('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;
}
`
Old
I'm still testing some javascript, but I wonder if the effect you wanted is something like this? I did a few things different, but the main things were using hide(), css(), slideUp(), slideDown(), and if / else statements. Here's a jsfiddle of the example
<script>
$(document).ready(function () {
var header = $("header");
var lastScrollTop = 0;
$(window).on("scroll", function () {
currentScrollTop = $(this).scrollTop();
if ($("body").scrollTop() > header.outerHeight()) {
if (currentScrollTop > lastScrollTop) {
if (header.css("position") == "fixed") {
header.slideUp();
} else {
header.css({
display: "none",
position: "fixed"
});
}
} else {
header.slideDown();
}
} else {
if (currentScrollTop === 0) {
header.css({
display: "block",
position: "static"
});
}
}
lastScrollTop = currentScrollTop;
});
});
</script>

Change background color if position fixed

I have this simple navigation that was built to hide a fixed header when scrolling down. When you scroll up it will reappear for easy navigation. It works great! However, I need it changed up a bit and not sure how to accomplish this.
When the position is fixed at the absolute top of the page I need the header to be transparent. When the position is then scrolled down and then scrolled up a little. I need the background to be blue until it reaches the absolute top then again change to transparent.
http://codepen.io/anon/pen/VYPGyg
here is the jQuery in question:
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;
}
Any help would be great!
I would use your nav-down and nav-up classes, since they're getting added anyways. When you use CSS to handle styling, you're (usually) better separating concerns amongst various aspects of your software. CSS should usually handle presentation, except where it's functionality is limited or not programmatic enough (enter javascript).
For example, take your .nav-down class and adjust the transparency:
Updated codepen:
http://codepen.io/anon/pen/YPNOLM
Added some logic to your function:
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');
}
// the 100 can be whatever height you think it should be at
if($(window).scrollTop() > 100) {
$('header').addClass('notTop')
} else {
$('header').removeClass('notTop')
}
}
lastScrollTop = st;
}
And an opacity property:
header.nav-down {
position: fixed;
width: 100%;
top: 0;
transition: top 0.2s ease-in-out;
z-index: 1;
background: #fff;
padding: 25px 0px 0px 0px;
opacity: 0.8
}
And:
header.nav-down.notTop {
background-color: blue
}

Categories