on page navigation IntersectionObserver

by hohoya33

HTML

<div class="slide slide--intro">
<h1>On page navigation Demo</h1>
</div>

<nav>
  <ul>
  <li><a class="active" href="#one">One</a></li>
  <li><a href="#two">Two</a></li>
  <li><a href="#three">Three</a></li>
  <li><a href="#four">Four</a></li>
  <li><a href="#five">Five</a></li>
  </ul>
</nav>
<section id="one">
<p>Slide One</p>
</section>
<section id="two">
<p>Slide Two</p>
</section>
<section id="three">
<p>Slide Three</p>
</section>
<section id="four">
<p>Slide Four</p>
</section>
<section id="five">
<p>Slide Five</p>
</section>

CSS

.slide {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
}
.slide--intro {
  flex-direction: column;
}

nav {
  position: sticky;
  width: 100%;
  top: 0;
  left: 0;
  right: 0;
  background-color: #fff;
}
nav ul {
  list-style-type: none;
  display: flex;
  align-items: center;
  justify-content: space-around;
  width: 100%;
  max-width: 800px;
  height: 50px;
  margin: 0 auto;
  padding: 0;
}
nav li {
  display: inline-block;
  padding: 5px;
}
nav a {
  display: block;
  height: 40px;
  padding: 0 20px;
  line-height: 40px;
  text-decoration: none;
  text-transform: uppercase;
  color: #323232;
  font-weight: bold;
  border-radius: 4px;
  transition: background-color 0.3s ease-in;
}
nav a:hover,
nav a:active,
nav a:focus {
  background-color: rgba(184,214,168,0.5);
}
nav a.active {
  background-color: rgba(184,214,168,0.5);
}
section {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
}
p {
  text-align: center;
  color: #fff;
  font-size: 3.5em;
  font-weight: bold;
  text-transform: uppercase;
}
#one {
  background-color: #6ca392;
}
#two {
  background-color: #ffa58c;
}
#three {
  background-color: #ff4f30;
}
#four {
  background-color: #576b51;
}
#five {
  background-color: #392a1b;
}

JavaScript

const changeNav = (entries, observer) => {
    entries.forEach((entry) => {
        // verify the element is intersecting
        if(entry.isIntersecting && entry.intersectionRatio >= 0.55) {
            // remove old active class
            document.querySelector('.active').classList.remove('active');
            // get id of the intersecting section
            var id = entry.target.getAttribute('id');
            // find matching link & add appropriate class
            var newLink = document.querySelector(`[href="#${id}"]`).classList.add('active');
        }
    });
}

// init the observer
const options = {
    threshold: 0.55
}

const observer = new IntersectionObserver(changeNav, options);

// target the elements to be observed
const sections = document.querySelectorAll('section');
sections.forEach((section) => {
    observer.observe(section);
});