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>
Related
I'm using this code to make my sticky navbar disappear on scroll down and re-appear on scroll up. However this code is pretty precise resulting sometimes in starting one of both animations without actually scrolling.
What I'm trying to achieve is that a user should scroll 20px down before the if statement runs. Same if they would scroll up again...
https://jsfiddle.net/as1tpbjw/2/
const body = document.querySelector("#navbar");;
let lastScroll = 0;
window.addEventListener("scroll", () => {
const currentScroll = window.pageYOffset;
if (currentScroll <= 0) {
body.classList.remove("scroll-up");
return;
}
if (currentScroll > lastScroll && !body.classList.contains("scroll-down")) {
body.classList.remove("scroll-up");
body.classList.add("scroll-down");
} else if (
currentScroll < lastScroll &&
body.classList.contains("scroll-down")
) {
body.classList.remove("scroll-down");
body.classList.add("scroll-up");
}
lastScroll = currentScroll;
});
As far as I can see, in my relatively old version of Firefox, it works well.
I added if (Math.abs(currentScroll - lastScroll) < 20) { return; } and this adds a 20px delay either way.
Also, that scroll-up class doesn't seem to be doing anything in the fiddle.
Update:
If you want an animation, you can replace the CSS for .scroll-down and add a transition to #navbar:
#navbar.scroll-down {
height: 0;
}
#navbar {
/* … */
transition: height .5s;
}
Not only does scroll-up do nothing, but the following code even breaks (doesn't show the navbar) when you scroll to the top:
if (currentScroll <= 0) {
body.classList.remove("scroll-up");
return;
}
You may want to remove it.
const body = document.querySelector("#navbar");
let lastScroll = 0;
window.addEventListener("scroll", () => {
const currentScroll = window.pageYOffset;
if (Math.abs(currentScroll - lastScroll) < 20) {
return;
}
if (currentScroll > lastScroll) {
body.classList.add("scroll-down");
} else {
body.classList.remove("scroll-down");
}
lastScroll = currentScroll;
});
body {
margin: 0;
min-height: 200vh;
}
#navbar.scroll-down {
height: 0;
}
#navbar {
height: 50px;
background: red;
position: sticky;
top: 0;
left: 0;
transition: height .5s;
}
<body>
<div id="navbar">
</div>
</body>
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";
}
});
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>
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;
});
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
}