【2024 Update】Pure CSS Method Implementation
In CSS, traditional animations are defined via the @keyframes rule and then controlled using the animation property to play. These animations typically run on a timeline independent of user scrolling. However, in Chrome 115 or later, a new CSS property animation-timeline: scroll(); is supported. This property allows you to associate animations with scroll events, creating scroll-driven animation effects, enabling us to implement a page scrollbar using pure CSS.
<style>
.container {
max-width: 800px;
margin: 0 auto;
padding: clamp(1rem, 2vw, 5rem);
}
.progress {
height: 5px;
background: #33a6b8;
border-radius:5px;
position: fixed;
top: 0;
left: 0;
width: 100%;
transform-origin: 0 50%;
animation: scaleProgress auto linear;
animation-timeline: scroll(root);
}
@keyframes scaleProgress {
0% {
transform: scaleX(0);
}
100% {
transform: scaleX(1);
}
}
</style>
<div class="progress"></div>
scrollHeight, scrollTop and clientHeight

Full webpage image
This is a complete webpage, where the area inside the red box (the visible area in the browser window) has a height of clientHeight. The distance from the red box area to the top is scrollTop, and the height of the entire webpage is scrollHeight. With this understanding, you can calculate the proportion of the current scroll position relative to the total page height: scrollTop / (scrollHeight - clientHeight). This proportion represents the percentage of the page the user has viewed.
Progress Bar
Here we use MDUI's progress bar, but we need to add position: fixed in the style to make it float at the top of the page.
Adding Code
After introducing the necessary code on the page, add a JS script and get the reading progress according to the method in the first part:
const TOTAL_HEIGHT = document.documentElement.scrollHeight;
const VIEWPORT_HEIGHT = document.documentElement.clientHeight;
const PROGRESS_BAR_ID = "进度条 ID";
const progressBar = document.getElementById(PROGRESS_BAR_ID);
window.onscroll = function() {
let scrollTop = document.body.scrollTop + document.documentElement.scrollTop;
let scrollPercent = (scrollTop / (TOTAL_HEIGHT - VIEWPORT_HEIGHT)) * 100;
progressBar.style.width = `${scrollPercent}%`;
// 如果页面内容不足以显示进度条,则隐藏进度条
if (TOTAL_HEIGHT <= VIEWPORT_HEIGHT) {
progressBar.style.display = 'none';
} else {
progressBar.style.display = 'block';
}
}
window.addEventListener('scroll', (event) => {
requestAnimationFrame(() => {
let scrollTop = document.body.scrollTop + document.documentElement.scrollTop;
let scrollPercent = (scrollTop / (TOTAL_HEIGHT - VIEWPORT_HEIGHT)) * 100;
progressBar.style.width = `${scrollPercent}%`;
});
});
This way you can have a reading progress bar.