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

React实现双组件垂直与水平同步滚动效果

React实现垂直滚动同步驱动水平组件滚动方案

实现效果参考:
效果示意图

实现逻辑

放弃原有transform旋转90度的实现思路(该方案易出现定位偏移、滚动条异常、移动端适配差的问题),直接监听页面垂直滚动事件,将垂直滚动的进度按比例映射为水平固定容器的横向滚动偏移,逻辑可控、调试成本低。
核心逻辑点:

  • 紫色长页面保留正常文档流,撑出页面垂直滚动高度
  • 蓝、绿色所在的水平滚动容器设置为fixed定位,固定在视口指定位置,隐藏自身滚动条
  • 监听window的scroll事件,计算当前垂直滚动进度,同步设置水平容器的scrollLeft值
  • 用requestAnimationFrame做滚动回调节流,保证滚动流畅不卡顿

修正后代码

样式代码(horzantalComponent.css)

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
.page{
    height: 300vh;
    background-color: purple;
    position: relative;
    z-index: 1;
}
.horizantalContainer{
    position: fixed;
    /* 水平容器默认固定在视口垂直居中位置,可自行修改top/bottom调整位置 */
    top: 50%;
    left: 0;
    transform: translateY(-50%);
    width: 100vw;
    height: 35vh;
    overflow: hidden;
    background-color: blue;
    z-index: 10;
} 
.wrapper{
    display: flex;
    height: 100%;
    width: 300vw;
}
.slide{
    height: 100%;
    width: 100vw;
    display: flex;
    align-items: center;
    padding: 2rem;
}
.slide:nth-child(1){
    background-color: lightblue;
    justify-content: flex-end;
}
.slide:nth-child(2){
    background-color: lightgreen;
}
.slide:nth-child(3){
    background-color: lightpink;
}

组件代码

import React, { useEffect, useRef } from 'react'
import "./horzantalComponent.css"
const HorzantalComponent = () => {
    const scrollContainerRef = useRef(null)
    const wrapperRef = useRef(null)

    useEffect(() => {
        const container = scrollContainerRef.current
        const wrapper = wrapperRef.current
        if (!container || !wrapper) return

        // 水平方向最大可滚动距离
        const maxHorizontalScroll = wrapper.scrollWidth - container.clientWidth
        // 垂直方向需要滚动的总行程:值越小水平滚动越快,值越大水平滚动越慢
        const verticalScrollRange = window.innerHeight * 2

        let ticking = false
        const handleScroll = () => {
            if (!ticking) {
                window.requestAnimationFrame(() => {
                    const scrollY = window.scrollY
                    // 计算滚动进度,限制在0-1区间避免越界
                    const scrollProgress = Math.min(Math.max(scrollY / verticalScrollRange, 0), 1)
                    // 同步水平滚动位置
                    container.scrollLeft = scrollProgress * maxHorizontalScroll
                    ticking = false
                })
                ticking = true
            }
        }

        // 绑定事件,passive配置提升滚动性能
        window.addEventListener('scroll', handleScroll, { passive: true })
        window.addEventListener('resize', handleScroll)
        // 初始化校准位置
        handleScroll()

        return () => {
            window.removeEventListener('scroll', handleScroll)
            window.removeEventListener('resize', handleScroll)
        }
    }, [])

    return (
        <div>
            <div className="page">
                <div className='horizantalContainer' ref={scrollContainerRef}>
                    <div className='wrapper' ref={wrapperRef}>
                        <div className='slide'> <p>Horizantal Slide component slide</p> </div>
                        <div className='slide'> </div>
                        <div className='slide'></div>
                    </div>
                </div>
            </div>
        </div>
    )
}

export default HorzantalComponent

可调参数说明

  • 调整水平组件固定位置:修改.horizantalContainer的定位属性,比如固定在顶部可设top: 0; transform: none;,固定在底部可设bottom: 0; transform: none;
  • 调整水平滚动速度:修改verticalScrollRange的取值,比如改为window.innerHeight * 3代表需要滚动3倍视口高度才能走完水平内容全程,滚动速度会变慢
  • 调整水平内容总宽度:修改.wrapper的width值,同步增减slide数量即可,代码会自动计算最大滚动距离,不需要手动改逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 20:36:21