CSS水平滚动动画:奇偶行反向滚动循环空白问题求助
解决块元素水平无缝循环滚动问题
问题背景
需要实现奇数行从右向左滚动、偶数行从左向右滚动的水平动画,当前已实现基础滚动效果,但元素滚出后会出现空白,无法形成无缝循环。
核心解决思路
要实现无缝循环,关键是让滚动内容在视觉上“首尾相连”。通过复制一份完全相同的滚动内容,让总长度变为原内容的两倍,配合调整动画的滚动距离,当原内容完全滚出容器时,复制的内容刚好衔接上来,视觉上就形成了无限循环的效果。
具体修改步骤
- 复制滚动内容:给每个
.ticker-line添加一份完全相同的.ticker-item列表 - 调整动画关键帧:
- 向左滚动动画:滚动距离改为原内容宽度的一半(即总内容的50%),从
translateX(0)到translateX(-50%) - 向右滚动动画:初始位置设为
translateX(-50%),滚动到translateX(0),反向实现无缝衔接
- 向左滚动动画:滚动距离改为原内容宽度的一半(即总内容的50%),从
- 确保内容不换行:给
.ticker-line添加flex-wrap: nowrap属性
完整代码示例
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> body { margin: 0; overflow: hidden; } .ticker-container { background-color: #333; color: #fff; } .ticker-line-container { overflow: hidden; margin-bottom: 50px; } .ticker-line { display: flex; gap: 50px; width: max-content; flex-wrap: nowrap; /* 确保内容不换行 */ } .ticker-item { width: 300px; height: 200px; box-sizing: border-box; } img { width: 100%; height: 100%; object-fit: cover; } @keyframes ticker-animation-left { 0% { transform: translateX(0); } 100% { transform: translateX(-50%); /* 滚动总内容的50%,即原内容的宽度 */ } } @keyframes ticker-animation-right { 0% { transform: translateX(-50%); /* 初始位置偏移原内容宽度 */ } 100% { transform: translateX(0); } } </style> </head> <body> <div class="ticker-container"> <div class="ticker-line-container"> <div class="ticker-line" style="animation: ticker-animation-left 15s linear infinite;"> <!-- 原内容 --> <div class="ticker-item"><img src="https://picsum.photos/300/200?random=1" alt="Image 1"></div> <div class="ticker-item"><img src="https://picsum.photos/300/200?random=2" alt="Image 2"></div> <div class="ticker-item"><img src="https://picsum.photos/300/200?random=3" alt="Image 3"></div> <div class="ticker-item"><img src="https://picsum.photos/300/200?random=4" alt="Image 4"></div> <div class="ticker-item"><img src="https://picsum.photos/300/200?random=5" alt="Image 5"></div> <div class="ticker-item"><img src="https://picsum.photos/300/200?random=6" alt="Image 6"></div> <div class="ticker-item"><img src="https://picsum.photos/300/200?random=7" alt="Image 7"></div> <div class="ticker-item"><img src="https://picsum.photos/300/200?random=8" alt="Image 8"></div> <div class="ticker-item"><img src="https://picsum.photos/300/200?random=9" alt="Image 9"></div> <div class="ticker-item"><img src="https://picsum.photos/300/200?random=10" alt="Image 10"></div> <!-- 复制的内容,实现无缝衔接 --> <div class="ticker-item"><img src="https://picsum.photos/300/200?random=1" alt="Image 1"></div> <div class="ticker-item"><img src="https://picsum.photos/300/200?random=2" alt="Image 2"></div> <div class="ticker-item"><img src="https://picsum.photos/300/200?random=3" alt="Image 3"></div> <div class="ticker-item"><img src="https://picsum.photos/300/200?random=4" alt="Image 4"></div> <div class="ticker-item"><img src="https://picsum.photos/300/200?random=5" alt="Image 5"></div> <div class="ticker-item"><img src="https://picsum.photos/300/200?random=6" alt="Image 6"></div> <div class="ticker-item"><img src="https://picsum.photos/300/200?random=7" alt="Image 7"></div> <div class="ticker-item"><img src="https://picsum.photos/300/200?random=8" alt="Image 8"></div> <div class="ticker-item"><img src="https://picsum.photos/300/200?random=9" alt="Image 9"></div> <div class="ticker-item"><img src="https://picsum.photos/300/200?random=10" alt="Image 10"></div> </div> </div> <div class="ticker-line-container"> <div class="ticker-line" style="animation: ticker-animation-right 15s linear infinite;"> <!-- 原内容 --> <div class="ticker-item"><img src="https://picsum.photos/300/200?random=11" alt="Image 11"></div> <div class="ticker-item"><img src="https://picsum.photos/300/200?random=12" alt="Image 12"></div> <div class="ticker-item"><img src="https://picsum.photos/300/200?random=13" alt="Image 13"></div> <div class="ticker-item"><img src="https://picsum.photos/300/200?random=14" alt="Image 14"></div> <div class="ticker-item"><img src="https://picsum.photos/300/200?random=15" alt="Image 15"></div> <div class="ticker-item"><img src="https://picsum.photos/300/200?random=16" alt="Image 16"></div> <div class="ticker-item"><img src="https://picsum.photos/300/200?random=17" alt="Image 17"></div> <div class="ticker-item"><img src="https://picsum.photos/300/200?random=18" alt="Image 18"></div> <div class="ticker-item"><img src="https://picsum.photos/300/200?random=19" alt="Image 19"></div> <div class="ticker-item"><img src="https://picsum.photos/300/200?random=20" alt="Image 20"></div> <!-- 复制的内容,实现无缝衔接 --> <div class="ticker-item"><img src="https://picsum.photos/300/200?random=11" alt="Image 11"></div> <div class="ticker-item"><img src="https://picsum.photos/300/200?random=12" alt="Image 12"></div> <div class="ticker-item"><img src="https://picsum.photos/300/200?random=13" alt="Image 13"></div> <div class="ticker-item"><img src="https://picsum.photos/300/200?random=14" alt="Image 14"></div> <div class="ticker-item"><img src="https://picsum.photos/300/200?random=15" alt="Image 15"></div> <div class="ticker-item"><img src="https://picsum.photos/300/200?random=16" alt="Image 16"></div> <div class="ticker-item"><img src="https://picsum.photos/300/200?random=17" alt="Image 17"></div> <div class="ticker-item"><img src="https://picsum.photos/300/200?random=18" alt="Image 18"></div> <div class="ticker-item"><img src="https://picsum.photos/300/200?random=19" alt="Image 19"></div> <div class="ticker-item"><img src="https://picsum.photos/300/200?random=20" alt="Image 20"></div> </div> </div> </div> </body> </html>
说明
- 复制内容时要保证和原内容完全一致,包括图片链接,这样滚动衔接时才不会出现断层
- 动画时长保持不变即可,因为滚动距离调整为原内容宽度,速度和原效果一致
- 若后续需要动态修改内容,需同步更新复制的那份内容,确保两者一致
内容的提问来源于stack exchange,提问作者Sergey Podgornyy
相关产品推荐
相关产品推荐

