
本文详解如何使用纯 CSS 构建真正无缝的无限滚动轮播组件,通过精确计算内容宽度、改用 transform: translateX() 替代 left 动画,并双份内容拼接策略,彻底消除循环时的视觉跳变与卡顿。
本文详解如何使用纯 css 构建真正无缝的无限滚动轮播组件,通过精确计算内容宽度、改用 `transform: translatex()` 替代 `left` 动画,并双份内容拼接策略,彻底消除循环时的视觉跳变与卡顿。
实现平滑无限滚动的关键在于:动画终点必须与起点完全对齐,且过渡过程不可中断或重置。原始代码中使用 left: -100% 导致位移基准为父容器宽度(而非内容总宽),造成动画距离不足;同时 .marquee-inner 的 width: 200% 依赖父级尺寸缩放,无法适配固定 580px 的 .marquee-item 及 40px 间距。
✅ 正确做法:精准宽度 + transform + 双倍内容
首先,明确单个 .marquee-item 宽度为 580px,gap: 40px 在 <span></span> 内生效,因此 每个 <span></span> 的总宽度 = 580px × 5 + 40px × 4 = 3060px(5 项 + 4 个间隙)。而轮播需无缝衔接,必须提供两组相同内容——当第一组完全移出视口时,第二组恰好完全进入,视觉上形成“无限”效果。
因此,.marquee-inner 的宽度应严格设为:
.marquee-inner {
width: calc((580px + 40px) * 5 + 40px); /* = 3060px */
}⚠️ 注意:
580px + 40px是每项含右侧间隙的逻辑单元,但末项无右侧 gap,故最终加回一个40px补足总间隙数(4 个),即5×580 + 4×40 = 3060px。立即学习“前端免费学习笔记(深入)”;
其次,动画必须基于元素自身尺寸计算位移。transform: translateX(-100%) 中的 100% 指当前 .marquee-inner 元素宽度(3060px),完美匹配滚动距离;而旧方案 left: -100% 的 100% 指父 .marquee-block 宽度(约 30% × 5 = 150% 容器宽),严重失准。
关键动画定义如下:
@keyframes marqueeLeft {
0% { transform: translateX(0); }
100% { transform: translateX(-3060px); } /* 或更简洁地:-100% */
}
/* 推荐使用 -100%,语义清晰且自动适配宽度变化 */? 完整可运行示例(精简优化版)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>CSS Infinite Marquee</title>
<style>
.marquee-wrapper {
background: #2F394C;
text-align: center;
padding: 20px 0;
}
.marquee-wrapper .container {
overflow: hidden;
}
.marquee-block {
--total-items: 5;
height: 150px;
margin: 20px auto;
background: #1B2531;
padding: 30px 0;
overflow: hidden;
position: relative;
width: calc(30% * var(--total-items)); /* 仅控制容器宽度,不影响滚动逻辑 */
}
.marquee-inner {
display: flex;
width: calc((580px + 40px) * 5 + 40px); /* 总内容宽:5项 + 4间隙 */
position: absolute;
animation: marqueeLeft 10s linear infinite; /* 延长周期提升流畅感 */
}
@keyframes marqueeLeft {
0% { transform: translateX(0); }
100% { transform: translateX(-100%); } /* ✅ 100% = .marquee-inner 自身宽度 */
}
.marquee-item {
width: 580px;
height: auto;
background: #00cc00;
display: flex;
align-items: center;
justify-content: center;
font-weight: 800;
font-size: 30px;
font-family: cursive;
color: white;
flex-shrink: 0; /* 防止被压缩 */
}
.marquee-inner span {
display: flex;
gap: 40px;
}
</style>
</head>
<body>
<div class="marquee-wrapper">
<div class="container">
<div class="marquee-block">
<div class="marquee-inner">
<!-- 第一组内容 -->
<span>
<div class="marquee-item"><p>1</p></div>
<div class="marquee-item"><p>2</p><div class="aritcle_card flexRow">
<div class="artcardd flexRow">
<a class="aritcle_card_img" href="/xiazai/skill5790" title="Json Schema Toolkit"><img
src="https://img.php.cn/upload/skill/000/000/081/179066171761941.jpg" alt="Json Schema Toolkit" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a href="/xiazai/skill5790" title="Json Schema Toolkit">Json Schema Toolkit</a>
<p>使用 JSON Schema 验证 JSON 数据,从示例 JSON 生成 schema,并将其转换为 TypeScript 接口、Python 数据类或 Markdown 文档。</p>
</div>
<a href="/xiazai/skill5790" title="Json Schema Toolkit" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a>
</div>
</div></div>
<div class="marquee-item"><p>3</p></div>
<div class="marquee-item"><p>4</p></div>
<div class="marquee-item"><p>5</p></div>
</span>
<!-- 第二组相同内容(实现无缝衔接) -->
<span>
<div class="marquee-item"><p>1</p></div>
<div class="marquee-item"><p>2</p></div>
<div class="marquee-item"><p>3</p></div>
<div class="marquee-item"><p>4</p></div>
<div class="marquee-item"><p>5</p></div>
</span>
</div>
</div>
</div>
</div>
</body>
</html>? 注意事项与进阶建议
-
flex-shrink: 0必须添加:防止.marquee-item在 flex 容器中被意外压缩,破坏580px固定宽度; - 动画时长建议 ≥8s:过短周期易暴露循环接缝,适当延长可显著提升视觉连续性;
-
避免
transition干扰:.marquee-item上的transition: all .2s会与transform动画冲突,应移除; -
响应式兼容性:本方案基于固定像素值(
580px),如需响应式,请改用clamp()或媒体查询动态调整--item-width变量,但核心公式calc((var(--item-width) + gap) * count + gap)保持不变; -
性能提示:
transform触发 GPU 加速,远优于left/top的重排重绘,是纯 CSS 轮播的性能基石。
至此,你已掌握构建专业级纯 CSS 无限轮播的核心原理:用 transform 锚定自身尺寸、用双份内容填补循环间隙、用精确 calc() 消除百分比歧义——无需一行 JavaScript,即可交付丝滑、稳定、高性能的视觉体验。

















