JSFiddle - React, Tailwind, and code Playground
by Jordan Sayner
HTML
<nav id="progress-nav">
<ul>
<li><a href="#bcorp">What is B-Corp?</a></li>
<li><a href="#renewables">Investing in Renewables</a></li>
<li><a href="#spaces">Community Spaces</a></li>
<li><a href="#initiatives">Other Initiatives</a></li>
<li><a href="#goals">Future Goals</a></li>
<li><a href="#progress">Our Progress</a></li>
</ul>
<div id="progress-line"></div>
</nav>
<!-- Sections -->
<section id="bcorp">...</section>
<section id="renewables">...</section>
<section id="spaces">...</section>
<section id="initiatives">...</section>
<section id="goals">...</section>
<section id="progress">...</section>
CSS
#progress-nav {
position: fixed;
top: 20px;
left: 50%;
transform: translateX(-50%);
width: 80%;
background: white;
padding: 10px 20px;
border-radius: 50px;
display: flex;
justify-content: space-between;
align-items: center;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
z-index: 1000;
}
#progress-nav ul {
display: flex;
width: 100%;
justify-content: space-between;
position: relative;
}
#progress-nav ul li {
list-style: none;
position: relative;
flex: 1;
text-align: center;
}
/* Dots */
#progress-nav ul li::before {
content: "";
position: absolute;
bottom: -10px;
left: 50%;
transform: translateX(-50%);
width: 8px;
height: 8px;
background: lightgray;
border-radius: 50%;
transition: background 0.3s ease;
}
#progress-nav ul li.active::before {
background: blue;
}
/* Progress Line */
#progress-line {
height: 3px;
width: 0%;
background: blue;
transition: width 0.3s ease;
}
#progress-nav ul li a {
text-decoration: none;
color: gray;
font-size: 14px;
transition: color 0.3s;
}
#progress-nav ul li.active a {
color: blue;
font-weight: bold;
}
section {
min-height: 150vh;
}
JavaScript
document.addEventListener("DOMContentLoaded", function () {
const sections = document.querySelectorAll("section");
const navLinks = document.querySelectorAll("#progress-nav ul li");
const progressLine = document.getElementById("progress-line");
function updateProgress() {
let scrollPosition = window.scrollY;
let totalHeight = document.body.scrollHeight - window.innerHeight;
let progressPercentage = (scrollPosition / totalHeight) * 100;
// Update progress line width
progressLine.style.width = progressPercentage + "%";
sections.forEach((section, index) => {
let top = section.offsetTop - 100; // Adjust for sticky nav
let bottom = top + section.clientHeight;
if (scrollPosition >= top && scrollPosition < bottom) {
navLinks.forEach((link) => link.classList.remove("active"));
navLinks[index].classList.add("active");
}
});
}
window.addEventListener("scroll", updateProgress);
updateProgress(); // Initial call
});