React滚动进度条本地失效求助(HTML设100%高度导致)
解决react-progressbar-on-scroll滚动进度条始终显示0%的问题
问题场景
使用react-progressbar-on-scroll实现滚动进度条功能,在线CodeSandbox示例运行正常,但本地环境中进度条的background线性渐变百分比始终显示0%,无法动态更新。经排查问题源于HTML标签设置了100%高度,且该设置属于模板必要内容无法移除。
现有代码
App.js
import React from "react"; import { BrowserRouter, Routes, Route } from "react-router-dom"; import ProgressBar from 'react-progressbar-on-scroll'; import './App.scss'; function App() { return ( <> <BrowserRouter> <header> <div>Header Content</div> </header> <ProgressBar color="red" height={8}/> <main className="flex-shrink-0"> <Routes> <Route path="/" element={ <> <React.Suspense fallback={<SuspenseLoader />}> <div>Home Content</div> </React.Suspense> </> } /> <Route path="*" element={ <> <React.Suspense fallback={<SuspenseLoader />}> <div>Content Not Found!</div> </React.Suspense> </> } /> </Routes> </main> <footer className="footer mt-auto"> <div>Footer Content</div> </footer> </BrowserRouter> </> ); } export default App;
package.json
{ "name": "react", "version": "0.1.0", "private": true, "dependencies": { "@emailjs/browser": "^3.6.2", "@react-google-maps/api": "^2.7.0", "@testing-library/jest-dom": "^5.16.2", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^13.5.0", "bootstrap": "^5.1.3", "bootstrap-icons": "^1.8.1", "node-sass": "^7.0.1", "react": "^17.0.2", "react-bootstrap": "^2.1.2", "react-dom": "^17.0.2", "react-hook-form": "^7.27.1", "react-masonry-css": "^1.0.16", "react-progressbar-on-scroll": "^2.0.0", "react-router-dom": "^6.2.2", "react-scripts": "5.0.0", "react-scroll": "^1.8.7", "react-slick": "^0.28.1", "slick-carousel": "^1.8.1", "web-vitals": "^2.1.4" }, "scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject" }, "eslintConfig": { "extends": [ "react-app", "react-app/jest" ] }, "browserslist": { "production": [ ">0.2%", "not dead", "not op_mini all" ], "development": [ "last 1 chrome version", "last 1 firefox version", "last 1 safari version" ] } }
问题原因
react-progressbar-on-scroll默认基于document.body的scrollHeight计算滚动进度,当HTML/Body标签设置100%高度时,document.body.scrollHeight会等于浏览器视口高度,无法正确获取页面实际内容的总高度,导致进度计算始终为0。
解决方案
直接自定义滚动进度条组件,绕开库的默认计算逻辑,基于document.documentElement的实际内容高度计算进度:
修改后的App.js代码
import React, { useState, useEffect } from "react"; import { BrowserRouter, Routes, Route } from "react-router-dom"; import './App.scss'; // 补全缺失的SuspenseLoader组件 const SuspenseLoader = () => <div>Loading...</div>; function App() { const [scrollProgress, setScrollProgress] = useState(0); useEffect(() => { const handleScroll = () => { // 计算页面可滚动的总高度:实际内容高度 - 视口高度 const totalScrollableHeight = document.documentElement.scrollHeight - window.innerHeight; // 当前滚动距离 const currentScrollTop = window.scrollY; // 计算进度百分比,避免除以0的情况 const progress = totalScrollableHeight > 0 ? (currentScrollTop / totalScrollableHeight) * 100 : 0; setScrollProgress(progress); }; // 添加滚动监听 window.addEventListener('scroll', handleScroll); // 初始化时计算一次进度 handleScroll(); // 组件卸载时移除监听 return () => window.removeEventListener('scroll', handleScroll); }, []); return ( <> <BrowserRouter> <header> <div>Header Content</div> </header> {/* 自定义滚动进度条,替代原库组件 */} <div style={{ height: '8px', backgroundColor: '#f0f0f0', position: 'sticky', top: 0, zIndex: 1000, width: '100%' }} > <div style={{ height: '100%', width: `${scrollProgress}%`, backgroundColor: 'red', transition: 'width 0.2s ease-in-out' }} /> </div> <main className="flex-shrink-0"> <Routes> <Route path="/" element={ <> <React.Suspense fallback={<SuspenseLoader />}> {/* 添加足够高度的内容让页面可滚动 */} <div style={{ minHeight: '2000px' }}>Home Content</div> </React.Suspense> </> } /> <Route path="*" element={ <> <React.Suspense fallback={<SuspenseLoader />}> <div>Content Not Found!</div> </React.Suspense> </> } /> </Routes> </main> <footer className="footer mt-auto"> <div>Footer Content</div> </footer> </BrowserRouter> </> ); } export default App;
方案说明
- 使用
useState管理滚动进度百分比,useEffect添加/移除滚动监听事件 - 基于
document.documentElement.scrollHeight获取页面实际内容总高度,减去视口高度得到可滚动的总距离 - 用当前滚动距离除以可滚动总距离,得到滚动进度百分比
- 自定义进度条样式,通过
width属性动态更新进度,添加过渡动画提升体验
内容的提问来源于stack exchange,提问作者clarkf
相关产品推荐
相关产品推荐

