interactions · scroll · lecture

Barre de progression de lecture

Fine barre qui se remplit au fur et à mesure de la lecture. Ici démontrée dans un cadre autonome (scrollez DANS le cadre) — sur un vrai site, remplace 'position: sticky' par 'position: fixed' pour qu'elle reste collée en haut de l'écran pendant tout le scroll de la page.

Voir le code source
<style>
.bn-reading-demo {
  padding: 2rem;
  font-family: 'Inter', sans-serif;
  background: #0B0F10;
}

/* Ce cadre (hauteur fixe + overflow-y: auto) ne sert QU'À LA DÉMO,
   pour recréer une "page qui scrolle" en miniature. Sur un vrai
   site, tu n'as pas besoin de ce cadre : la page entière fait
   office de zone de scroll. */
.bn-reading-demo__box {
  position: relative;
  height: 260px;
  overflow-y: auto;
  border: 1px solid rgba(230, 228, 221, 0.12);
  border-radius: 8px;
}

/* "sticky" colle la barre en haut DU CADRE tant qu'on scrolle
   dedans — c'est l'équivalent, à l'échelle du cadre, de ce que fait
   "position: fixed" à l'échelle d'une vraie page. Sur ton site,
   remplace "sticky" par "fixed" (et retire le cadre autour) pour
   qu'elle reste collée à l'écran plutôt qu'à ce conteneur. */
.bn-reading-bar {
  position: sticky;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  background: rgba(230, 228, 221, 0.1);
  z-index: 2;
}

.bn-reading-bar__fill {
  height: 100%;
  width: 0%;
  background: #E6E4DD;
  transition: width 0.1s linear;
}

.bn-reading-demo__article {
  padding: 1.5rem;
}

.bn-reading-demo__kicker {
  display: block;
  font-size: 0.7rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #979793;
  margin-bottom: 0.4rem;
}

.bn-reading-demo__title {
  font-family: 'Bebas Neue', sans-serif;
  font-size: 1.4rem;
  letter-spacing: 0.02em;
  color: #E6E4DD;
  margin: 0 0 1rem;
}

.bn-reading-demo__article p {
  color: #979793;
  font-size: 0.85rem;
  line-height: 1.65;
  margin: 0 0 1rem;
}

.bn-reading-demo__hint {
  margin: 0.75rem 0 0;
  color: #5C6160;
  font-size: 0.75rem;
}

</style>

<div class="bn-reading-demo" data-fx-root>

  <!-- Ce cadre à hauteur fixe et scroll interne n'existe QUE pour
       la démo, afin que tu puisses voir l'effet sans avoir à
       scroller toute la page. Sur un vrai site, la barre reprend
       les mêmes classes mais sans ce cadre autour — voir la note
       dans le CSS. -->
  <div class="bn-reading-demo__box">
    <div class="bn-reading-bar"><div class="bn-reading-bar__fill"></div></div>

    <div class="bn-reading-demo__article">
      <span class="bn-reading-demo__kicker">Réflexion</span>
      <h3 class="bn-reading-demo__title">L'inconnu comme horizon</h3>

      <p>Dans un monde saturé d'informations, Blaig Nova choisit la voie du silence et de la profondeur. Ici, chaque projet est une exploration.</p>
      <p>Chaque réflexion, une tentative de comprendre ce qui nous échappe. Nous avançons dans l'inconnu, guidés par la curiosité, la rigueur et l'intuition.</p>
      <p>Explorer, créer, partager : trois mouvements essentiels pour donner forme à ce qui n'existe pas encore.</p>
      <p>Blaig Nova n'apporte pas de réponses toutes faites. Il ouvre des pistes, pose des questions, et invite chacun à trouver sa propre direction.</p>
      <p>Ce n'est pas un simple portfolio. C'est un espace vivant, en constante évolution, où les idées prennent forme et où les projets deviennent des territoires à explorer.</p>
    </div>
  </div>

  <p class="bn-reading-demo__hint">↕ Scrollez à l'intérieur du cadre ci-dessus pour voir la barre se remplir.</p>
</div>


<script>
/* ==========================================================
   BARRE DE PROGRESSION DE LECTURE
   Dans cette démo, le cadre a son propre scroll interne (voir le
   CSS) : on écoute donc simplement le scroll de CE cadre, pas celui
   de la page entière. Sur un vrai site (sans le cadre de démo), il
   suffit d'écouter le scroll de "window" à la place.
   ========================================================== */

(function () {
  const root = document.querySelector('.bn-reading-demo[data-fx-root]');
  if (!root) return;

  const box = root.querySelector('.bn-reading-demo__box');
  const fill = root.querySelector('.bn-reading-bar__fill');

  function update() {
    const maxScroll = box.scrollHeight - box.clientHeight;
    const percent = maxScroll > 0 ? (box.scrollTop / maxScroll) * 100 : 0;
    fill.style.width = `${percent}%`;
  }

  box.addEventListener('scroll', update, { passive: true });
  update();
})();

</script>