基于ReactJS与CSS实现无缝循环滚动动画的问题求助
React 无缝循环滚动动画解决方案
问题原因
- 仅渲染单份列表内容,滚动到末尾后容器需从底部回滚到顶部,出现空白等待期
- 动画起始位置使用
100vw,与内容高度不匹配,导致滚动逻辑混乱
修复方案
核心思路
通过复制一份列表内容,让容器内存在两份完全相同的卡片,结合精准的动画滚动距离设置,实现滚动到第二份末尾时,第一份刚好衔接上,视觉上无空白无缝循环。
修改后的代码
React 组件代码(App.js)
import { useRef, useEffect, useState } from "react"; import Card from "./Card.js"; import "./styles.css"; const data = [ { Name: "1" }, { Name: "2" }, { Name: "3" }, { Name: "4" }, { Name: "5" } ]; export default function App() { const containerRef = useRef(null); const contentRef = useRef(null); const [animationState, setAnimationState] = useState("paused"); const [singleContentHeight, setSingleContentHeight] = useState(0); useEffect(() => { if (contentRef.current) { // 获取单份内容的实际高度 const height = contentRef.current.offsetHeight / 2; setSingleContentHeight(height); setAnimationState("running"); } }, []); // 渲染两份相同的卡片列表,实现无缝衔接 const renderCards = [...data, ...data].map((el, index) => ( <Card key={index} cardName={el.Name} /> )); return ( <div className="App"> <div className="scroll-container" ref={containerRef}> <div className="scroll-content" ref={contentRef} style={{ animationPlayState: animationState, "--scroll-height": `${singleContentHeight}px` }} > {renderCards} </div> </div> </div> ); }
CSS 代码(styles.css)
.App { overflow: hidden; height: 224px; /* 等于卡片高度+上下margin总和:200 + 12*2 */ } .scroll-container { overflow: hidden; height: 100%; } .scroll-content { display: flex; flex-direction: column; animation: scrollVertical 5s linear infinite; } /* 使用CSS变量动态控制滚动距离,确保动画首尾衔接 */ @keyframes scrollVertical { 0% { transform: translateY(0); } 100% { transform: translateY(calc(var(--scroll-height, 0px) * -1)); } } .card { width: 200px; height: 200px; background: #ffefef; box-shadow: 0px 1px 4px 1px rgba(158, 151, 151, 0.25); border-radius: 15px; margin: 12px; padding: 12px; }
关键说明
- 复制列表内容后,滚动容器内始终有一份完整的列表处于可视区域,另一份作为衔接补充
- 动画滚动距离严格等于单份内容的高度,动画结束时容器刚好回到第二份内容的起始位置,也就是第一份内容的初始状态,实现无间隙循环
- 使用CSS变量动态传递内容高度,避免硬编码数值,适配不同数量的卡片
内容的提问来源于stack exchange,提问作者alainber82
相关产品推荐
相关产品推荐

