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

如何合并React项目中react-spring引发的双滚动条?

解决React-Spring Parallax与页面内容共存时的双滚动条问题

问题描述

我正在学习react-spring,通过npx create-react-app name创建开发环境。单独使用App.js时一切正常,但在index.html中加入<main>内容后出现了双滚动条——页面和parallax组件各自独立滚动。尝试用::-webkit-scrollbar { display: none}隐藏滚动条,但两个滚动区域仍可单独滚动,希望将它们合并为一个统一的滚动行为。

相关代码

App.js

import logo from './logo.svg';
import './App.css';
import { Parallax, ParallaxLayer } from '@react-spring/parallax';
import moon from './img/moon.jpg';
import city from './img/city.jpg';
import cat  from './img/cat.gif';

function App() {
  return (
   <div className='animation'>
      <Parallax pages={4} className='parallax'>
        <ParallaxLayer offset={0} style={{
          backgroundImage: `url(${moon})`,
          backgroundSize: 'cover'
        }}></ParallaxLayer>

        <ParallaxLayer offset={1} 
        sticky={{start: 1.2, end: 2.5}}
        style={{
          display: "block",
          marginLeft: "auto",
          marginRight: "auto",
          width: "50%",
        }}>
          <img src={cat}></img>
        </ParallaxLayer>

        <ParallaxLayer offset={2} factor={2} speed={1} style={{background: "linear-gradient(130deg, rgba(0,0, 0,1) 0%, rgba(0,29,39,1) 100%)"}}></ParallaxLayer>

        <ParallaxLayer offset={3} speed={0.9}
          style={{
            backgroundImage: `url(${city})`,
            backgroundSize: "cover"
          }}></ParallaxLayer>
        
        <ParallaxLayer offset={3} speed={3}><h2>Nice init!</h2></ParallaxLayer>
        <ParallaxLayer offset={5} speed={1}></ParallaxLayer>
        <ParallaxLayer offset={6} speed={1}></ParallaxLayer>

      </Parallax>
    </div>
  );
}

export default App;

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta
      name="description"
      content="Web site created using create-react-app"
    />
    <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <title>React App</title>
  </head>
  <body>
    <main>
      <div class="main">Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.   Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.   Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.   Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.      </div>
    </main>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
  </body>
</html>

问题根源

双滚动条的本质是两个独立滚动容器共存:

  • 页面的<body>/<main>内容过长,触发了浏览器全局滚动
  • React-Spring的<Parallax>组件默认会创建自身的滚动容器,导致出现两个互不关联的滚动区域

解决方法

方案1:将index.html内容移入React组件(推荐)

React项目的最佳实践是把页面内容放在React组件中,而非直接写在index.html的<body>里。将<main>中的内容作为一个ParallaxLayer加入App.js:

修改后的App.js核心部分:

function App() {
  return (
   <div className='animation'>
      <Parallax pages={5} className='parallax'>
        {/* 原有所有ParallaxLayer */}
        
        {/* 新增:原index.html中的main内容 */}
        <ParallaxLayer offset={4} speed={1}>
          <div className="main">
            {/* 原main内的文本内容 */}
          </div>
        </ParallaxLayer>
      </Parallax>
    </div>
  );
}

之后删除index.html中的<main>标签,只保留<div id="root"></div>和<noscript>。

方案2:禁用全局滚动,让Parallax接管整个页面

如果必须保留index.html中的内容,需让Parallax成为唯一滚动容器:

  1. 在全局CSS(如App.css)中禁用html和body的滚动:
html, body {
  margin: 0;
  padding: 0;
  overflow: hidden;
  height: 100vh;
}
  1. 调整Parallax组件样式,使其占满视口并允许内部滚动:
.parallax {
  height: 100vh;
  overflow-y: auto;
}
  1. 将index.html中的<main>内容调整为Parallax组件的一部分,避免内容超出视口触发额外滚动。

关键提示

React-Spring的Parallax组件设计为自主管理滚动逻辑,因此最好让它成为页面的唯一滚动容器,避免同时存在多个独立滚动区域。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 14:47:00