如何使用CSS实现滚动后中间停留再继续滚动的跑马灯效果?
CSS实现带停留效果的向上跑马灯
核心思路是通过CSS @keyframes 拆分动画时间轴,滚动过程仅占用小段时间,剩余时间保持位移不变实现停留效果,性能比JS定时器实现更稳定,时间控制也更精准。
1 修正HTML结构
先修复原有HTML的标签闭合错误,新增一层条目包裹容器用于控制动画,同时在末尾复制第一条条目实现无缝滚动:
<section> <div class="placard" id="js-placard"> <!-- 新增包裹容器 --> <div class="placard-wrapper"> <div class="placard_item"> <span class="megaphone">HTML</span> <p class="placard_text"></p> </div> <div class="placard_item"> <span class="megaphone"></span> <p class="placard_text">CSS</p> </div> <div class="placard_item"> <span class="megaphone"></span> <p class="placard_text">javascript</p> </div> <!-- 复制第一条实现无缝滚动 --> <div class="placard_item"> <span class="megaphone">HTML</span> <p class="placard_text"></p> </div> </div> </div> </section>
2 调整CSS代码
保留原有样式基础上,新增动画规则:
.placard { background-color: #fff0d8; padding: 8px 0px; margin-bottom: 12px; height: 36px; overflow: hidden; } /* 新增包裹容器样式 */ .placard-wrapper { animation: scrollUp 6.9s infinite linear; } .placard_item { line-height: 36px; height: 36px; display: flex; align-items: center; } .placard .placard_text { font-size: 13px; letter-spacing: 0.43px; margin: 0; } .placard .megaphone { display: inline-block; width: 20px; height: 20px; background-color: red; background-size: cover; margin-right: 8px; } /* 滚动动画定义:3个条目,每个停留2s,滚动耗时0.3s,总时长= (2+0.3)*3 = 6.9s */ @keyframes scrollUp { /* 第一个条目停留:0% ~ 29% 对应0~2s */ 0%, 29% { transform: translateY(0); } /* 滚动到第二个条目:29% ~ 33% 对应2~2.3s */ 33% { transform: translateY(-36px); } /* 第二个条目停留:33% ~ 62% 对应2.3~4.3s */ 33%, 62% { transform: translateY(-36px); } /* 滚动到第三个条目:62% ~ 66% 对应4.3~4.6s */ 66% { transform: translateY(-72px); } /* 第三个条目停留:66% ~ 95% 对应4.6~6.6s */ 66%, 95% { transform: translateY(-72px); } /* 滚动到复制的第一个条目:95% ~ 100% 对应6.6~6.9s,重置到0位时无缝 */ 100% { transform: translateY(-108px); } } /* 可选:鼠标悬停暂停动画 */ .placard:hover .placard-wrapper { animation-play-state: paused; }
3 动态适配条目数量(可选)
如果条目数量不固定,可以加少量JS动态生成动画规则,不需要复杂的滚动逻辑,原有JS的滚动逻辑可以全部删除:
const itemHeight = 36; const stayTime = 2000; // 每个条目停留时间ms const scrollTime = 300; // 滚动动画耗时ms const items = document.querySelectorAll('.placard_item'); const itemCount = items.length; // 复制第一个元素到末尾 document.querySelector('.placard-wrapper').appendChild(items[0].cloneNode(true)); // 动态生成keyframes const totalTime = (stayTime + scrollTime) * itemCount; let keyframes = ''; let currentPercent = 0; for(let i=0; i<itemCount; i++){ const stayPercent = (stayTime / totalTime) * 100; const scrollPercent = (scrollTime / totalTime) * 100; keyframes += `${currentPercent}%, ${currentPercent + stayPercent}% { transform: translateY(${-i * itemHeight}px); }`; currentPercent += stayPercent + scrollPercent; if(i < itemCount -1){ keyframes += `${currentPercent}% { transform: translateY(${-(i+1) * itemHeight}px); }`; } else { keyframes += `100% { transform: translateY(${-(i+1) * itemHeight}px); }`; } } // 插入样式 const style = document.createElement('style'); style.innerHTML = `@keyframes scrollUp {${keyframes}} .placard-wrapper { animation: scrollUp ${totalTime/1000}s infinite linear; }`; document.head.appendChild(style); // 单个条目时关闭动画 if(itemCount <=1) { document.querySelector('.placard-wrapper').style.animation = 'none'; }
内容的提问来源于stack exchange,提问作者WEI A
相关产品推荐
相关产品推荐

