Добавить/убрать класс active, vanilla JS

Есть скрипт, который добавляет/убирает класс active с nav-link в зависимости от секции. Но есть одно но, количество секций не равно количеству nav-link, поэтому необходимо, чтобы класс active убирался, если в данный момент неактивная секция. Сейчас же, если мы на неактивной секции, то класс active будет на nav-link предыдущей активной секции. Надеюсь понятно объяснил, если не поняли - спрашивайте. Так же snippet добавил, там показано как это сейчас работает.

const links = document.querySelectorAll('.nav-link');
const sections = document.querySelectorAll('.forJS');
  function changeLinkState() {
    let index = sections.length;

    while(--index && window.scrollY + 50 < sections[index].offsetTop) {}

    links.forEach((link) => link.classList.remove('active'));
    links[index].classList.add('active');
  }

changeLinkState();
window.addEventListener('scroll', changeLinkState);
section{
height:100vh;
scroll-y:auto;
}
.nav-link.active{
  color: red;
}
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"/>
<body>
<header class="fixed-top">
  <nav class="navbar navbar-expand-lg navCustom">
    <div class="container">

          <ul class="navbar-nav justify-content-center">
            <li class="nav-item">
              <a class="nav-link" href="#main">Main</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="#about">About us</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="#portfolio">Portfolio</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="#contacts">Contacts</a>
            </li>
          </ul>
    </div>
  </nav>
</header>

<section class="forJS text-center">Some info 1</section>
<section class="text-center">Some info 2</section>
<section class="text-center">Some info 3</section>
<section class="forJS text-center">Some info 4</section>
<section class="forJS text-center">Some info 5</section>
<section class="text-center">Some info 6</section>
<section class="text-center">Some info 7</section>
<section class="text-center">Some info 8</section>
<section class="text-center">Some info 9</section>
<section class="forJS text-center">Some info 10</section>
</body>


Ответы (1 шт):

Автор решения: UserTest013

Никогда не используйте addEventListener на 'scroll' для контроля видимых областей. Для этого существует IntersectionObserver, на улице уже 2021 год.

const links = document.querySelectorAll('.nav-link');
const sections = [... document.querySelectorAll('.forJS')];

const callback = (entries) => {
  links.forEach((link) => link.classList.remove('active'));
  const elem = entries.find((entry) => entry.isIntersecting);
  if (elem) {
    const index = sections.findIndex((section) => section === elem.target);
    links[index].classList.add('active');
  }
}

let observer = new IntersectionObserver(callback, {
  rootMargin: '0px',
  threshold: 0.5
});

sections.forEach((section) => observer.observe(section));
section {
  height: 100vh;
  scroll-y: auto;
}
.nav-link.active{
  color: red;
}
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"/>
<body>
<header class="fixed-top">
  <nav class="navbar navbar-expand-lg navCustom">
    <div class="container">

          <ul class="navbar-nav justify-content-center">
            <li class="nav-item">
              <a class="nav-link" href="#main">Main</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="#about">About us</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="#portfolio">Portfolio</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="#contacts">Contacts</a>
            </li>
          </ul>
    </div>
  </nav>
</header>

<section class="forJS text-center">Some info 1</section>
<section class="forJS text-center">Some info 2</section>
<section class="forJS text-center">Some info 3</section>
<section class="text-center">Some info 4</section>
<section class="text-center">Some info 5</section>
<section class="text-center">Some info 6</section>
<section class="text-center">Some info 7</section>
<section class="text-center">Some info 8</section>
<section class="text-center">Some info 9</section>
<section class="forJS text-center">Some info 10</section>
</body>

→ Ссылка