Sauter les bases, je connais PHP
La base
Le JavaScript côté navigateur
Les librairies incontournables
Pour aller plus loin
Cas Pratiques (ES2015)

Dans ce tutoriel nous allons voir comment écouter le scroll d'une page afin d'activer l'élément du menu correspondant. C'est une technique indispensable qui est très utilisé sur les sites "one page" mais aussi pour créer des sommaires dynamiques.

Le fonctionnement

Afin d'identifier les éléments à observer on utilisera un attribut data-spy. Chaque élément aura aussi un id qui sera utilisé par les liens du menu.

<nav>
  <a href="#section1">Section 1</a>
  <a href="#section2">Section 2</a>
  <a href="#section3">Section 3</a>
  <a href="#section4">Section 4</a>
  <a href="contact.html">Contact</a>
</nav>
<main>
    <section id="section1" data-spy>Section 1</section>
    <section id="section2" data-spy>Section 2</section>
    <section id="section3" data-spy>Section 3</section>
    <section id="section4" data-spy>Section 4</section>
</main>

Ensuite on utilisera l'IntersectionObserver afin de trouver quelle section est visible à l'écran. Afin de simplifier la détection de l'élément on va chercher à obtenir l'intersection avec une barre de 1px situé à 40% de hauteur (en jouant sur le rootMargin).

const y = Math.round(window.innerHeight * ratio)
const observer = new IntersectionObserver(callback, {
  rootMargin: `-${window.innerHeight - y - 1}px 0px -${y}px 0px`
})

Dans le callback on activera l'élément visible à l'écran

const callback = function (entries) {
  entries.forEach(function (entry) {
    if (entry.isIntersecting) {
      activate(entry.target)
    }
  })
}

const activate = function (elem) {
  const id = elem.getAttribute('id')
  const anchor = document.querySelector(`a[href="#${id}"]`)
  if (anchor === null) {
    return null
  }
  anchor.parentElement
    .querySelectorAll('.active')
    .forEach(node => node.classList.remove('active'))
  anchor.classList.add('active')
}

On adaptera la fonction activate en fonction de la situation.