You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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;

方案说明

  1. 使用useState管理滚动进度百分比,useEffect添加/移除滚动监听事件
  2. 基于document.documentElement.scrollHeight获取页面实际内容总高度,减去视口高度得到可滚动的总距离
  3. 用当前滚动距离除以可滚动总距离,得到滚动进度百分比
  4. 自定义进度条样式,通过width属性动态更新进度,添加过渡动画提升体验

内容的提问来源于stack exchange,提问作者clarkf

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 17:01:08