
本文介绍一种不依赖 标签、无需 jQuery 的纯 CSS + 轻量 JS 方案,通过动态计算内容宽度并配合双副本平滑位移,实现响应式环境下滚动速度恒定、内容完整显示的现代字幕效果。
本文介绍一种不依赖 `
在构建响应式滚动字幕时,核心挑战在于:既要保证内容完整连续滚动(无跳变、无截断),又要维持视觉速度恒定——无论视口尺寸如何变化,也无论客户输入多少文字。原生 <marquee></marquee> 已废弃,而常见纯 CSS 方案(如 transform: translateX(-100%))往往因动画周期固定,导致内容越长滚动越慢、越短越快,违背“恒速”需求。
✅ 解决方案关键设计
双副本无缝衔接机制
将内容复制至少两遍(推荐 2–3 倍),配合transform: translateX(-50%)实现视觉上无限循环:当第一份内容完全移出左边界时,第二份恰好补位,消除跳跃感。这是实现“无中断滚动”的基础。-
动态动画时长计算(JS 辅助)
CSS 本身无法获取元素实际渲染宽度,因此需用极简 JS 获取.duck的offsetWidth或getComputedStyle().width,并将其注入 CSS 自定义属性(如--w),再通过calc()动态生成动画周期:animation: scroll-left calc(var(--s) * var(--w) / 2000) linear infinite;
其中
--s: 10s表示“理想状态下滚动 2000px 所需时间”,--w是实际宽度(单位 px),从而确保像素级移动速度恒定(例如始终为 200px/s)。 弹性布局与最小宽度兜底
使用display: flex; justify-content: space-around均匀分布子项,并设置min-width: 200vw防止小屏下内容被过度压缩或单字断裂,兼顾可读性与响应性。
✅ 完整可运行代码
<div class="pizza">
<p class="duck">
<span class="red">Start Lorem ipsum dolor sit amet...</span>
<span class="green">Start Lorem ipsum dolor sit amet...</span>
<span class="blue">Start Lorem ipsum dolor sit amet...</span>
<!-- 至少重复一次,确保无缝衔接 -->
<span class="red">Start Lorem ipsum dolor sit amet...</span>
<span class="green">Start Lorem ipsum dolor sit amet...</span>
<span class="blue">Start Lorem ipsum dolor sit amet...</span>
</p>
</div>/* 文字样式 */
.red { color: red; }
.green { color: green; }
.blue { color: blue; }
/* 容器:隐藏溢出、禁止换行 */
.pizza {
line-height: 60px;
font-size: 16px;
overflow: hidden;
position: relative;
white-space: nowrap;
}
/* 滚动主体:flex 布局 + 动态动画 */
p.duck {
display: flex;
justify-content: space-around;
--s: 10s; /* 基准速度:滚动 2000px 用 10 秒 → 200px/s */
animation: scroll-left calc(var(--s) * var(--w) / 2000) linear infinite;
width: fit-content;
min-width: 200vw; /* 防小屏塌陷 */
}
@keyframes scroll-left {
0% { transform: translateX(0); }
100% { transform: translateX(-50%); } /* 关键!非 -100% */
}
p.duck:hover {
animation-play-state: paused;
}// 动态注入宽度变量(兼容 resize)
function setUp() {
const duck = document.querySelector('.duck');
if (duck) {
const widthPx = parseFloat(getComputedStyle(duck).width);
duck.style.setProperty('--w', widthPx);
}
}
window.addEventListener('load', setUp);
window.addEventListener('resize', setUp);⚠️ 注意事项与优化建议
-
内容复制策略:务必确保内容重复 ≥2 次,且所有
<span></span>保持相同结构与样式,避免因 DOM 差异导致位移错位。 -
性能考量:该方案全程使用
transform和will-change: transform(可手动添加)触发 GPU 加速,无重排(reflow),适合长文本。 -
无障碍(a11y)提醒:自动滚动可能影响部分用户,建议添加
prefers-reduced-motion查询,在系统开启“减少运动”时暂停动画:@media (prefers-reduced-motion: reduce) { p.duck { animation-play-state: paused; } } -
替代方案权衡:若项目已引入 Vue/React,可考虑用
IntersectionObserver实现更精细的滚动控制;但对静态站点,本方案以最小 JS 代价达成最佳平衡。
至此,您已拥有一套真正响应式、速度恒定、语义清晰且面向未来的滚动字幕实现——告别 <marquee></marquee>,拥抱现代 CSS 与轻量 JS 的协同力量。


















