Reputation: 409
I am creating a basic web page where I made a very basic transparent navbar with a white fontor font overlapping a dark background banner. The font turns black black when scrolling down and reaching a light background (at least that's the goal).
The thing is, the change is not responsive, meaning that depending on the device and the size of the screen, the navbar change will not occur exactly at the bottom end of the banner. Is there a way to do that? Here is my code:
1/ HTML
home skills portfolio bio resume contact
<div class="banner">
<div class="background-gradient">
<video autoplay muted loop id="myVideo">
<source src="images/Background_Loop_small.mp4" type="video/mp4">
</video>
</div>
<div class="content">
<div class="presentation">
<img src="images/avatar2.jpg" id="avatar">
<h1 id="place-title">Olivier Girardot</h1>
<h3 id="text-white">Junior Full-Stack Web Developper</h3>
<section id="section01" class="demo">
<div class="container" style="height: 80px"></div>
<a href="#section02"><span></span><span></span><span></span></a>
</section>
</div>
</div>
</div>
2/ CSS
.navbar {
margin: 0;
background: transparent;
position: fixed;
color: white;
display: flex;
height: 60px;
z-index: 10;
}
.navbar-links {
display: flex;
align-items: center;
padding: 0px 10px;
}
.navbar-links a:hover {
opacity: 0.7;
}
.menu {
position: relative;
display: flex;
align-items: center;
right: 0;
}
.menu a {
color: white;
text-decoration: none;
font-size: 1vw;
font-weight: 500;
padding: 0px 10px;
}
.menu a:hover {
border-bottom: solid white 1px;
}
.navbar-under {
margin: 0;
background: #f0f0f0;
position: fixed;
color: black;
display: flex;
height: 30px;
z-index: 10;
}
.menu-under {
position: relative;
display: flex;
align-items: center;
right: 0;
}
.menu-under a {
color: black;
text-decoration: none;
font-size: 1vw;
font-weight: 500;
padding: 0px 10px;
}
.menu-under a:hover {
border-bottom: solid black 1px;
}
3/ Javascript
const navbar = document.querySelector(".navbar");
const menu = document.querySelector(".menu");
window.addEventListener('scroll', () => {
if (window.scrollY > 700) {
navbar.classList.remove('navbar');
navbar.classList.add("navbar-under");
}
});
window.addEventListener('scroll', () => {
if (window.scrollY < 700) {
navbar.classList.remove("navbar-under");
navbar.classList.add('navbar');
}
});
window.addEventListener('scroll', () => {
if (window.scrollY > 700) {
menu.classList.remove('menu');
menu.classList.add("menu-under");
}
});
window.addEventListener('scroll', () => {
if (window.scrollY < 700) {
menu.classList.remove("menu-under");
menu.classList.add('menu');
}
});
So I guess the issue comes from window.scrollY > 700
or window.scrollY < 700
, is there a way to make that responsive, and make the navbar change exactly at the bottom of the banner?
Upvotes: 0
Views: 237
Reputation: 6742
Instead of listening to scroll event you should have a look at Intersection Observer (IO)
With this you can react whenever an element overlaps with another element or the viewport, so you could use this for your navigation bar.
Here is a quick example on how this might work. It's not perfect but it should provide a good starting point for you to flesh it out.
If you need to support older browsers like IE, have a look at the official polyfill from w3c
const sections = document.querySelectorAll('div');
const config = {
rootMargin: '0px',
threshold: [.2, .9]
};
const observer = new IntersectionObserver(function (entries, self) {
entries.forEach(entry => {
if (entry.isIntersecting) {
var headerEl = document.querySelector('header');
if (entry.intersectionRatio > 0.9) {
//intersection ratio bigger than 90%
//-> set header according to target
headerEl.className=entry.target.dataset.header;
} else {
//-> check if element is coming from top or from bottom into view
if (entry.target.getBoundingClientRect().top < 0 ) {
headerEl.className=entry.target.dataset.header;
}
}
}
});
}, config);
sections.forEach(section => {
observer.observe(section);
});
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.g-100vh {
height: 100vh
}
header {
min-height: 50px;
position: fixed;
background-color: green;
width: 100%;
}
header.white-menu {
color: white;
background-color: black;
}
header.black-menu {
color: black;
background-color: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<header>
<p>Header Content </p>
</header>
<div class="grid-30-span g-100vh white-menu" style="background-color:darkblue;" data-header="white-menu">
</div>
<div class="grid-30-span g-100vh black-menu" style="background-color:lightgrey;" data-header="black-menu">
</div>
<div class="grid-30-span g-100vh white-menu" style="background-color:darkblue;" data-header="white-menu">
</div>
Upvotes: 1