I have re-created a working simplified version of my issue: a skinny banner (which hides when user scrolls down), main navigation (that should stick to top of page when user scrolls down) and some dummy content to make scrolling possible.
I'm achieving this current implementation by adding a class sb-scrolling
to the skinny banner (display: none
) when the scroll position is less more than or equal to the main-nav
height.
However, when scrolling slowly, there is a flicker which seems to be between hiding and showing the skinny banner. Can anyone guide as to where I've gone wrong?
UPDATE: answers below still have "flicker" present (must scroll down/up slowly to spot)
const skinnyBanner = document.querySelector('.skinny-banner');
const mainNav = document.querySelector('.main-nav');
// Handle page scroll
let scrollpos = window.scrollY;
const navHeight = mainNav.offsetHeight;
window.addEventListener('scroll', function() {
scrollpos = window.scrollY;
if (scrollpos >= navHeight) {
mainNav.classList.add('scrolling');
skinnyBanner.classList.add('sb-scrolling');
} else {
mainNav.classList.remove('scrolling');
skinnyBanner.classList.remove('sb-scrolling');
}
});
header {
display: block;
position: sticky;
top: 0;
}
.skinny-banner {
display: flex;
align-items: center;
justify-content: center;
background-color: lightgrey;
width: 100%;
height: 40px;
}
.main-nav {
display: flex;
align-items: center;
justify-content: center;
background-color: yellow;
width: 100%;
height: 140px;
}
.skinny-nav-menu {
display: flex;
gap: 24px;
}
.sb-scrolling {
display: none !important;
}
.scrolling {
min-height: 70px !important;
}
.content-block-1 {
height: 300px;
background-color: orange;
display: flex;
align-items: center;
justify-content: center;
}
.content-block-2 {
height: 300px;
background-color: lightblue;
display: flex;
align-items: center;
justify-content: center;
}
.content-block-3 {
height: 300px;
background-color: lightcyan;
display: flex;
align-items: center;
justify-content: center;
}
<header>
<nav>
<div class="skinny-banner">SKINNY BANNER THAT IS HIDDEN WHEN SCROLLING DOWN</div>
<div class="main-nav">
MAIN NAVIGATION THAT SHOULD ALWAYS BE VISIBLE
</div>
</nav>
</header>
<div class="content-block-1">RANDOM PAGE CONTENT</div>
<div class="content-block-2">RANDOM PAGE CONTENT</div>
<div class="content-block-3">RANDOM PAGE CONTENT</div>
The only thing missing is a transition: all 0.2s linear;
in .skinny-banner
. The rest is from @AlanOmar
const skinnyBanner = document.querySelector('.skinny-banner');
const mainNav = document.querySelector('.main-nav');
// Handle page scroll
let scrollpos = window.scrollY;
const navHeight = mainNav.offsetHeight;
window.addEventListener('scroll', function() {
scrollpos = window.scrollY;
if (scrollpos >= navHeight) {
skinnyBanner.classList.add('sb-scrolling');
} else {
skinnyBanner.classList.remove('sb-scrolling');
}
});
header {
display: block;
position: sticky;
top: 0;
}
.skinny-banner {
display: flex;
align-items: center;
justify-content: center;
background-color: lightgrey;
width: 100%;
height: 40px;
transition: all 0.2s linear;
}
.main-nav {
display: flex;
align-items: center;
justify-content: center;
background-color: yellow;
width: 100%;
height: 140px;
}
.skinny-nav-menu {
display: flex;
gap: 24px;
}
.sb-scrolling {
height: 0 !important;
padding: 0;
transition: all 0.2s linear;
overflow:hidden;
}
.content-block-1 {
height: 300px;
background-color: orange;
display: flex;
align-items: center;
justify-content: center;
}
.content-block-2 {
height: 300px;
background-color: lightblue;
display: flex;
align-items: center;
justify-content: center;
}
.content-block-3 {
height: 300px;
background-color: lightcyan;
display: flex;
align-items: center;
justify-content: center;
}
<header>
<nav>
<div class="skinny-banner">SKINNY BANNER THAT IS HIDDEN WHEN SCROLLING DOWN</div>
<div class="main-nav">
MAIN NAVIGATION THAT SHOULD ALWAYS BE VISIBLE
</div>
</nav>
</header>
<div class="content-block-1">RANDOM PAGE CONTENT</div>
<div class="content-block-2">RANDOM PAGE CONTENT</div>
<div class="content-block-3">RANDOM PAGE CONTENT</div>
UPDATE
transition: height 0.2s linear;
should be enough.