Scroll Progress Number

Displays the current scroll progress as a zero-padded percentage number, updated in real time via a GSAP ScrollTrigger scrub on the full document body.

gsapscrolltriggerscrollprogresscounter

Setup — External Scripts

Setup: External Scripts
html
<script src="https://cdn.jsdelivr.net/npm/gsap@3.12.5/dist/gsap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.12.5/dist/ScrollTrigger.min.js"></script>

Code

index.html
html
<p data-progress-nr="" class="progress-nr">00</p>
styles.css
css
.progress-nr {
  margin: 0px;
  font-size: 5em;
  font-weight: 500;
  line-height: 1;
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
script.js
javascript
gsap.registerPlugin(ScrollTrigger);

function initScrollProgressNumber() {

  const progressCounter = document.querySelector('[data-progress-nr]');

  ScrollTrigger.create({
    trigger: document.body,
    start: 'top top',
    end: 'bottom bottom',
    scrub: 0.5,
    onUpdate: (self) => {
      const progress = Math.round(self.progress * 100); // Calculate progress as a percentage
      progressCounter.textContent = progress.toString().padStart(2, '0'); // Update counter
    },
  });
}

// Initialize Scroll Progress Number
document.addEventListener('DOMContentLoaded', () => {
  initScrollProgressNumber();
});

Guide

Overview

A ScrollTrigger instance spans the entire document body and fires onUpdate on every scroll tick. The progress value (0–1) is multiplied by 100, rounded, and written as a zero-padded two-digit string into the counter element.

Attribute

Add data-progress-nr to any element you want to use as the counter. The script targets it with querySelector, so only one element per page is supported.

Scrub

scrub: 0.5 adds a small lag so the number smoothly catches up to the scroll position rather than jumping. Set to true for instant updates or a higher number for more lag.