المعرفة:: JavaScript الحالة::مؤرشفة المراجع:: The Complete JavaScript Course 2022 From Zero to Expert


<header>
  <nav class="nav">...</nav>
</header>
 
<section class="section" id="section--1">
/* NAVIGATION */
.nav {
  display: flex;
  justify-content: space-between;
  align-items: center;
  height: 9rem;
  width: 100%;
  padding: 0 6rem;
  z-index: 100;
}
 
/* nav and stickly class at the same time */
.nav.sticky {
  position: fixed;
  background-color: rgba(255, 255, 255, 0.95);
}
  • The idea for stick navigation bar is to add sticky class (which changes the position to fixed) to the nav element whenever it moves over top of the view port.
  • This can be done by listening to Scroll Event and once the next section top coordinate is less than window’s current top coordinate the sticky class is added.
  • But this approach isn’t recommend because:
    ,-JavaScript-Events#^scrollevent
  • Instead, it’s better to use Intersection Observer API.

Classic Way

const section1 = document.querySelector('#section--1');
const nav = document.querySelector('.nav');
 
const initialCoords = section1.getBoundingClientRect();
console.log(initialCoords);
window.addEventListener('scroll', function () {
  console.log(window.scrollY);
  if (window.scrollY > initialCoords.top) nav.classList.add('sticky');
  else nav.classList.remove('sticky');
});

Using Intersection Observer API

  • We want the navigation bar to be sticky when the header moves completely out of the view, so we will observe the header element.
  • root will be null because we want to observe the entire view port.
  • threshold could be 0, but it’s better to set it to the distance between the start of the section and navigation bar height.
// Sticky navigation: Intersection Observer API
const header = document.querySelector('.header');
const navHeight = nav.getBoundingClientRect().height;
 
const stickyNav = function (entries) {
  // const entry = entries[0];
  const [entry] = entries;
  // console.log(entry);
 
  if (!entry.isIntersecting) nav.classList.add('sticky');
  else nav.classList.remove('sticky');
};
 
const headerObserver = new IntersectionObserver(stickyNav, {
  root: null,
  threshold: 0,
  // rootMargin: `-90px`,
  rootMargin: `-${navHeight}px`,
});
 
headerObserver.observe(header);