Scroll Progress Bar
A fixed top-of-page progress bar animated with GSAP ScrollTrigger scrubbed to the full document scroll. Includes an optional click-to-scroll feature using ScrollToPlugin that jumps to the clicked position on the bar.
Setup — External Scripts
<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>
<!-- Optional if you want to have the 'click to scroll to' functionality-->
<script src="https://cdn.jsdelivr.net/npm/gsap@3.12.5/dist/ScrollToPlugin.min.js"></script>Code
<div class="progress-bar-wrap">
<div class="progress-bar"></div>
</div>.progress-bar-wrap {
z-index: 10;
cursor: pointer;
width: 100%;
height: 1.5rem;
transition: background-color .2s;
position: fixed;
inset: 0% 0% auto;
}
.progress-bar-wrap:hover {
background-color: #0000000d;
}
.progress-bar {
transform-origin: 0%;
transform-style: preserve-3d;
background-color: #ff4c24;
width: 100%;
height: 100%;
transform: scale3d(0, 1, 1);
}gsap.registerPlugin(ScrollTrigger, ScrollToPlugin);
function initScrollProgressBar() {
const progressBar = document.querySelector('.progress-bar');
const progressBarWrap = document.querySelector('.progress-bar-wrap');
// Animate the progress bar as you scroll
gsap.to(progressBar, {
scaleX: 1,
ease: 'none', // no ease, we control smoothness with the 'scrub' property
scrollTrigger: {
trigger: document.body, // Track the entire page
start: 'top top',
end: 'bottom bottom',
scrub: 0.5, // control the amount of time it takes for the bar to catch up with scroll position
},
});
// Click listener to scroll to a specific position, feel free to remove if you dont want it!
progressBarWrap.addEventListener('click', (event) => {
const clickX = event.clientX;
const progress = clickX / progressBarWrap.offsetWidth;
const scrollPosition = progress * (document.body.scrollHeight - window.innerHeight);
gsap.to(window, {
scrollTo: scrollPosition,
duration: 0.725,
ease: 'power3.out',
});
});
}
// Initialize Scroll Progress Bar
document.addEventListener('DOMContentLoaded', () => {
initScrollProgressBar();
});Guide
Overview
The inner .progress-bar starts at scaleX(0) and is tweened to scaleX(1) via a ScrollTrigger that spans the full document body. transform-origin: 0% makes it grow from left to right.
Scrub
scrub: 0.5 makes the bar lag slightly behind the scroll position for a smooth feel. Set to true for an instant lock or increase the value for more drag.
Click to Scroll
The click listener on .progress-bar-wrap calculates what percentage along the bar was clicked, converts it to a scroll position, and animates the window there with ScrollToPlugin. Remove the listener and the ScrollToPlugin script tag if you don't need this feature.