Вы можете использовать IntersectionObserver для мониторинга просматриваемого содержимого и соответственно обновлять классы навигационных элементов.Вот простой пример.
const io = new IntersectionObserver((entries, observer) => {
entries.forEach((entry) => {
const navEl = document.querySelector(`[href="#${entry.target.id}"]`)
if (entry.intersectionRatio > 0) {
navEl.classList.add('in-view')
} else {
navEl.classList.remove('in-view')
}
})
})
document.querySelectorAll('h3').forEach((h3) => {
io.observe(h3)
})
ul {
position: fixed;
top: 0;
right: 0;
background: white;
padding: 2em;
}
div {
height:10rem;
background: #ddd;
}
.in-view {
color: red;
}
<ul>
<li><a href="#1">One</a></li>
<li><a href="#2">Two</a></li>
<li><a href="#3">Three</a></li>
<li><a href="#4">Four</a></li>
<li><a href="#5">Five</a></li>
</ul>
<h3 id="1">One</h3>
<div></div>
<h3 id="2">Two</h3>
<div></div>
<h3 id="3">Three</h3>
<div></div>
<h3 id="4">Four</h3>
<div></div>
<h3 id="5">Five</h3>
<div></div>