I created a navbar with sticky. The idea is that, when the user scroll down, the navbar goes has relative position until the user scrolls up or when they reach the end of the webpage. I used javascript to add the sticky class during these two events. The problem I am facing is, since the navbar is being taken out of the document flow and having a fixed position- it is causing the entire webpage to shift up. To solve this I have added a pseudo element of same height that takes the place of navbar whenever sticky is activated. I want to know if this is the right way to solve this problem. Is this complicating the problem as I can solve this without a pseudo element just by using the position of my navbar as absolute. I am attaching part of my code for reference
function scrollDetect() {
const navbar = document.getElementById("navbar");
const placeholder = document.querySelector(".navbar-placeholder");
let lastScroll = 0;
window.addEventListener("scroll", () => {
const currentScroll = document.documentElement.scrollTop || document.body.scrollTop;
if (currentScroll > 0 && lastScroll <= currentScroll) {
navbar.classList.remove("sticky");
placeholder.style.display = "none"; // Hide the placeholder
} else {
navbar.classList.add("sticky", "z-index-999999");
placeholder.style.display = "block"; // Show the placeholder to maintain space
}
lastScroll = currentScroll;
if (currentScroll < 100) {
navbar.classList.remove("sticky");
placeholder.style.display = "none"; // Hide the placeholder
}
});
}
scrollDetect();
.navbar-placeholder {
height: 4.5rem;
display: none;
}
.main-navbar {
position: relative;
display: inline-flex;
width: 100%;
top: 3.4rem;
height: 4.5rem;
align-items: center;
justify-content: space-between;
background-color: red;
}
.sticky {
position: fixed;
top: 0;
width: 100%;
animation: faceInEffect 0.3s;
-webkit-animation: faceInEffect 0.3s;
border-bottom: none;
}
@keyframes faceInEffect {
from {
top: -5rem;
}
to {
top: 0rem;
}
}
.content-for-scroll {
position: relative;
top: 100rem;
<div class="navbar-placeholder"></div>
<div class="main-navbar" id="navbar">
<a>hello</a>
</div>
<div class="content-for-scroll">
<a>hello</a>
</div>
2
Answers
Yes this is way over complicated. Look at this example of using the css property
position: sticky;
. I have put amargin-top: 20px;
on the<header>
element to show an initial gap. The position of the<header>
is relatively positioned until the viewport was scrolled such that the element would be less than0px
from the top. After that threshold, the<header>
would be fixed to0px
from the top. There is no JS involved, although you can add JS to decide to add a sticky class based on some browser detected or user interaction event but this CSS feature is native and well supported.See here for further reading on CSS position.
Something terribly simple and really similar to the desired:
toggle navigation bar on scroll-down and always show navigation on scroll-up — consists in using position sticky for the navigation element, and control the
translate
property (for the Y axis) via JavaScript that basically toggles a.is-hidden
class:To change the trigger height point in which the navbar initially hides, change to i.e:
elNav.offsetHeight / 2
or any other value.To conclude
the above example does not necessitates to set any static heights, to use any placeholders, and works pretty good on any website that needs to show the navigation as soon as the user starts to scroll up, with the addition to show the navigation bar at the far end (scrolled to bottom) — without much heavyweight coding.
For a similar solution, as reference see: Hide nav bar when user stops scrolling