CSS实现跑马灯效果-案例
示例图


控制速度

设计思路
使用CSS动画和transform属性创建平滑的滚动效果,通过@keyframes控制动画过程,并利用:hover伪类实现悬停暂停功能。
代码
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>CSS 跑马灯效果 - 完整实现与优化</title><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"><style>* {margin: 0;padding: 0;box-sizing: border-box;font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;}:root {--primary-color: #4361ee;--secondary-color: #3a0ca3;--accent-color: #4cc9f0;--dark-color: #1a1a2e;--light-color: #f8f9fa;--success-color: #4caf50;--warning-color: #ff9800;--danger-color: #f44336;--animation-speed: 20s;--border-radius: 12px;--box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);--transition: all 0.3s ease;}body {background: linear-gradient(135deg, var(--dark-color), var(--secondary-color));color: var(--light-color);min-height: 100vh;padding: 40px 20px;display: flex;flex-direction: column;align-items: center;line-height: 1.6;}.container {max-width: 1200px;width: 100%;margin: 0 auto;}header {text-align: center;margin-bottom: 50px;padding: 30px;background: rgba(255, 255, 255, 0.05);border-radius: var(--border-radius);backdrop-filter: blur(10px);box-shadow: var(--box-shadow);}h1 {font-size: 3rem;margin-bottom: 15px;text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);background: linear-gradient(90deg, var(--accent-color), var(--primary-color));-webkit-background-clip: text;background-clip: text;color: transparent;}.subtitle {font-size: 1.2rem;color: rgba(255, 255, 255, 0.8);max-width: 800px;margin: 0 auto;}h2 {font-size: 1.8rem;margin: 40px 0 20px;color: var(--accent-color);text-align: center;position: relative;padding-bottom: 10px;}h2::after {content: '';position: absolute;bottom: 0;left: 50%;transform: translateX(-50%);width: 100px;height: 3px;background: linear-gradient(90deg, transparent, var(--accent-color), transparent);}h3 {font-size: 1.5rem;margin: 25px 0 15px;color: var(--accent-color);}.section {margin-bottom: 60px;}.marquee-container {overflow: hidden;position: relative;padding: 25px 0;margin: 30px 0;background: rgba(255, 255, 255, 0.05);border-radius: var(--border-radius);box-shadow: var(--box-shadow);border: 1px solid rgba(255, 255, 255, 0.1);}.marquee-container::before, .marquee-container::after {content: '';position: absolute;top: 0;width: 100px;height: 100%;z-index: 2;}.marquee-container::before {left: 0;background: linear-gradient(90deg, rgba(26, 26, 46, 0.9), transparent);}.marquee-container::after {right: 0;background: linear-gradient(90deg, transparent, rgba(26, 26, 46, 0.9));}.marquee {display: flex;width: max-content;animation: marquee var(--animation-speed) linear infinite;}.marquee:hover {animation-play-state: paused;}.text-marquee {font-size: 2.5rem;font-weight: bold;white-space: nowrap;}.text-marquee span {padding: 0 30px;text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);display: flex;align-items: center;}.text-marquee i {margin-right: 10px;color: var(--accent-color);}.image-marquee {display: flex;}.image-item {width: 200px;height: 150px;margin: 0 15px;border-radius: 8px;overflow: hidden;box-shadow: 0 4px 8px rgba(0, 0, 0, 0.4);transition: var(--transition);position: relative;}.image-item:hover {transform: scale(1.05);box-shadow: 0 8px 16px rgba(0, 0, 0, 0.6);}.image-item img {width: 100%;height: 100%;object-fit: cover;}.mixed-marquee {display: flex;}.mixed-item {display: flex;align-items: center;margin: 0 20px;background: rgba(255, 255, 255, 0.1);border-radius: 10px;padding: 15px;min-width: 350px;transition: var(--transition);}.mixed-item:hover {background: rgba(255, 255, 255, 0.15);transform: translateY(-5px);}.mixed-icon {font-size: 2.5rem;margin-right: 15px;color: var(--accent-color);}.mixed-content {flex: 1;}.mixed-title {font-weight: bold;font-size: 1.2rem;margin-bottom: 5px;}.mixed-desc {font-size: 0.9rem;color: rgba(255, 255, 255, 0.7);}.marquee-reverse {animation-direction: reverse;}.marquee-fast {animation-duration: 15s;}.marquee-slow {animation-duration: 30s;}.controls {display: flex;justify-content: center;gap: 15px;margin: 20px 0;flex-wrap: wrap;}button {padding: 12px 25px;background: var(--primary-color);color: white;border: none;border-radius: 50px;font-weight: bold;cursor: pointer;transition: var(--transition);box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);display: flex;align-items: center;gap: 8px;}button:hover {background: var(--secondary-color);transform: translateY(-2px);box-shadow: 0 6px 12px rgba(0, 0, 0, 0.3);}button.active {background: var(--accent-color);color: var(--dark-color);}.explanation {background: rgba(255, 255, 255, 0.05);padding: 30px;border-radius: var(--border-radius);margin: 30px 0;backdrop-filter: blur(5px);box-shadow: var(--box-shadow);}.code-example {background: rgba(0, 0, 0, 0.7);color: #fff;padding: 20px;border-radius: 10px;margin: 20px 0;font-family: 'Courier New', monospace;overflow-x: auto;position: relative;border-left: 4px solid var(--accent-color);}.code-example pre {margin: 0;}.code-header {display: flex;justify-content: space-between;align-items: center;margin-bottom: 15px;padding-bottom: 10px;border-bottom: 1px solid rgba(255, 255, 255, 0.1);}.code-title {font-weight: bold;color: var(--accent-color);}.copy-btn {background: rgba(255, 255, 255, 0.1);color: white;border: none;padding: 5px 10px;border-radius: 4px;cursor: pointer;font-size: 0.8rem;transition: var(--transition);}.copy-btn:hover {background: rgba(255, 255, 255, 0.2);}.note {background: rgba(76, 201, 240, 0.1);padding: 15px;border-radius: 8px;margin: 15px 0;border-left: 4px solid var(--accent-color);}.features {display: grid;grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));gap: 20px;margin: 30px 0;}.feature-card {background: rgba(255, 255, 255, 0.05);padding: 25px;border-radius: var(--border-radius);text-align: center;transition: var(--transition);box-shadow: var(--box-shadow);}.feature-card:hover {transform: translateY(-5px);background: rgba(255, 255, 255, 0.08);}.feature-icon {font-size: 2.5rem;color: var(--accent-color);margin-bottom: 15px;}.feature-title {font-size: 1.3rem;margin-bottom: 10px;color: var(--accent-color);}.implementation-steps {margin: 30px 0;}.step {margin-bottom: 25px;padding: 20px;background: rgba(255, 255, 255, 0.05);border-radius: var(--border-radius);}.step-number {display: inline-block;width: 30px;height: 30px;background: var(--accent-color);color: var(--dark-color);border-radius: 50%;text-align: center;line-height: 30px;font-weight: bold;margin-right: 10px;}footer {margin-top: 60px;text-align: center;color: rgba(255, 255, 255, 0.7);font-size: 0.9rem;padding: 20px;border-top: 1px solid rgba(255, 255, 255, 0.1);width: 100%;}/* 动画定义 */@keyframes marquee {0% {transform: translateX(0);}100% {transform: translateX(-50%);}}@keyframes fadeIn {from {opacity: 0;transform: translateY(20px);}to {opacity: 1;transform: translateY(0);}}.fade-in {animation: fadeIn 0.8s ease forwards;}/* 响应式设计 */@media (max-width: 768px) {h1 {font-size: 2.2rem;}.text-marquee {font-size: 1.8rem;}.image-item {width: 160px;height: 120px;}.mixed-item {min-width: 280px;}.features {grid-template-columns: 1fr;}}@media (max-width: 480px) {h1 {font-size: 1.8rem;}.text-marquee {font-size: 1.4rem;}.image-item {width: 120px;height: 90px;}.mixed-item {min-width: 220px;padding: 10px;}button {padding: 10px 20px;font-size: 0.9rem;}}</style>
</head>
<body><div class="container"><header class="fade-in"><h1>CSS 跑马灯效果</h1><p class="subtitle">纯CSS实现的文字、图片和混合内容跑马灯,支持暂停、速度控制和多种动画效果</p></header><section class="section fade-in"><h2>文字跑马灯</h2><div class="marquee-container"><div class="marquee text-marquee"><span><i class="fas fa-star"></i> 欢迎来到CSS跑马灯世界!</span><span><i class="fas fa-code"></i> 纯CSS实现</span><span><i class="fas fa-bolt"></i> 无需JavaScript!</span><span><i class="fas fa-pause"></i> 可悬停暂停</span><span><i class="fas fa-star"></i> 欢迎来到CSS跑马灯世界!</span><span><i class="fas fa-code"></i> 纯CSS实现</span><span><i class="fas fa-bolt"></i> 无需JavaScript!</span><span><i class="fas fa-pause"></i> 可悬停暂停</span></div></div></section><section class="section fade-in"><h2>图片跑马灯</h2><div class="marquee-container"><div class="marquee image-marquee"><div class="image-item"><img src="https://picsum.photos/200/150?random=1" alt="示例图片"></div><div class="image-item"><img src="https://picsum.photos/200/150?random=2" alt="示例图片"></div><div class="image-item"><img src="https://picsum.photos/200/150?random=3" alt="示例图片"></div><div class="image-item"><img src="https://picsum.photos/200/150?random=4" alt="示例图片"></div><div class="image-item"><img src="https://picsum.photos/200/150?random=5" alt="示例图片"></div><div class="image-item"><img src="https://picsum.photos/200/150?random=6" alt="示例图片"></div><div class="image-item"><img src="https://picsum.photos/200/150?random=7" alt="示例图片"></div><div class="image-item"><img src="https://picsum.photos/200/150?random=8" alt="示例图片"></div></div></div></section><section class="section fade-in"><h2>混合内容跑马灯</h2><div class="marquee-container"><div class="marquee mixed-marquee"><div class="mixed-item"><div class="mixed-icon"><i class="fas fa-palette"></i></div><div class="mixed-content"><div class="mixed-title">CSS动画</div><div class="mixed-desc">使用@keyframes创建平滑动画效果</div></div></div><div class="mixed-item"><div class="mixed-icon"><i class="fas fa-magic"></i></div><div class="mixed-content"><div class="mixed-title">悬停暂停</div><div class="mixed-desc">鼠标悬停时动画暂停,提升交互体验</div></div></div><div class="mixed-item"><div class="mixed-icon"><i class="fas fa-tachometer-alt"></i></div><div class="mixed-content"><div class="mixed-title">速度控制</div><div class="mixed-desc">可调节动画速度,适应不同场景</div></div></div><div class="mixed-item"><div class="mixed-icon"><i class="fas fa-sync-alt"></i></div><div class="mixed-content"><div class="mixed-title">无缝循环</div><div class="mixed-desc">通过内容复制实现无缝滚动效果</div></div></div><div class="mixed-item"><div class="mixed-icon"><i class="fas fa-palette"></i></div><div class="mixed-content"><div class="mixed-title">CSS动画</div><div class="mixed-desc">使用@keyframes创建平滑动画效果</div></div></div><div class="mixed-item"><div class="mixed-icon"><i class="fas fa-magic"></i></div><div class="mixed-content"><div class="mixed-title">悬停暂停</div><div class="mixed-desc">鼠标悬停时动画暂停,提升交互体验</div></div></div><div class="mixed-item"><div class="mixed-icon"><i class="fas fa-tachometer-alt"></i></div><div class="mixed-content"><div class="mixed-title">速度控制</div><div class="mixed-desc">可调节动画速度,适应不同场景</div></div></div><div class="mixed-item"><div class="mixed-icon"><i class="fas fa-sync-alt"></i></div><div class="mixed-content"><div class="mixed-title">无缝循环</div><div class="mixed-desc">通过内容复制实现无缝滚动效果</div></div></div></div></div></section><section class="section fade-in"><h2>反向跑马灯</h2><div class="marquee-container"><div class="marquee text-marquee marquee-reverse"><span><i class="fas fa-arrow-left"></i> 这个跑马灯是反向滚动的!</span><span><i class="fas fa-rocket"></i> CSS动画强大!</span><span><i class="fas fa-mouse-pointer"></i> 尝试悬停暂停效果</span><span><i class="fas fa-arrow-left"></i> 这个跑马灯是反向滚动的!</span><span><i class="fas fa-rocket"></i> CSS动画强大!</span><span><i class="fas fa-mouse-pointer"></i> 尝试悬停暂停效果</span></div></div></section><section class="section fade-in"><h2>速度控制</h2><div class="controls"><button id="speed-fast" onclick="changeSpeed('fast')"><i class="fas fa-tachometer-alt-fast"></i> 加速</button><button id="speed-normal" onclick="changeSpeed('normal')" class="active"><i class="fas fa-tachometer-alt"></i> 正常速度</button><button id="speed-slow" onclick="changeSpeed('slow')"><i class="fas fa-tachometer-alt-slow"></i> 减速</button><button onclick="toggleAnimation()" id="toggle-btn"><i class="fas fa-pause"></i> 暂停所有动画</button></div></section><section class="section fade-in"><h2>核心特性</h2><div class="features"><div class="feature-card"><div class="feature-icon"><i class="fas fa-code"></i></div><div class="feature-title">纯CSS实现</div><p>无需JavaScript,仅使用CSS动画和转换属性</p></div><div class="feature-card"><div class="feature-icon"><i class="fas fa-pause-circle"></i></div><div class="feature-title">悬停暂停</div><p>鼠标悬停时暂停动画,提供更好的交互体验</p></div><div class="feature-card"><div class="feature-icon"><i class="fas fa-tachometer-alt"></i></div><div class="feature-title">速度控制</div><p>可动态调整动画速度,适应不同需求</p></div><div class="feature-card"><div class="feature-icon"><i class="fas fa-mobile-alt"></i></div><div class="feature-title">响应式设计</div><p>适配各种屏幕尺寸,移动设备友好</p></div></div></section><section class="section fade-in"><h2>实现原理</h2><div class="explanation"><p>CSS跑马灯使用<code>@keyframes</code>动画和<code>transform: translateX()</code>实现水平移动效果。</p><div class="implementation-steps"><h3>实现步骤</h3><div class="step"><div class="step-number">1</div><h3>创建动画关键帧</h3><p>使用@keyframes定义从0%到100%的动画过程,通过transform: translateX(-50%)实现元素向左移动50%的宽度。</p><div class="code-example"><div class="code-header"><div class="code-title">CSS 动画关键帧</div><button class="copy-btn" onclick="copyCode(this)">复制代码</button></div><pre><code>@keyframes marquee {0% {transform: translateX(0);}100% {transform: translateX(-50%);}
}</code></pre></div></div><div class="step"><div class="step-number">2</div><h3>应用动画到元素</h3><p>将动画应用到跑马灯元素,设置无限循环和线性时间函数。</p><div class="code-example"><div class="code-header"><div class="code-title">CSS 动画应用</div><button class="copy-btn" onclick="copyCode(this)">复制代码</button></div><pre><code>.marquee {display: flex;width: max-content;animation: marquee 20s linear infinite;
}</code></pre></div></div><div class="step"><div class="step-number">3</div><h3>实现悬停暂停</h3><p>通过:hover伪类和animation-play-state属性实现悬停时暂停动画。</p><div class="code-example"><div class="code-header"><div class="code-title">悬停暂停效果</div><button class="copy-btn" onclick="copyCode(this)">复制代码</button></div><pre><code>.marquee:hover {animation-play-state: paused;
}</code></pre></div></div><div class="step"><div class="step-number">4</div><h3>实现无缝滚动</h3><p>通过复制内容实现无缝滚动效果。当内容滚动到一半时,原始内容开始处刚好接上。</p><div class="code-example"><div class="code-header"><div class="code-title">HTML 结构示例</div><button class="copy-btn" onclick="copyCode(this)">复制代码</button></div><pre><code><div class="marquee"><span>内容1</span><span>内容2</span><span>内容3</span><!-- 重复内容实现无缝滚动 --><span>内容1</span><span>内容2</span><span>内容3</span>
</div></code></pre></div></div></div><div class="note"><p><strong>技术要点:</strong> 为了实现无缝滚动,需要复制一份内容(或使内容足够长),这样当内容滚动到一半时,原始内容开始处刚好接上,形成无缝循环效果。</p></div><h3>JavaScript 控制功能</h3><p>通过JavaScript动态修改CSS类来实现速度控制功能。</p><div class="code-example"><div class="code-header"><div class="code-title">JavaScript 速度控制</div><button class="copy-btn" onclick="copyCode(this)">复制代码</button></div><pre><code>function changeSpeed(speed) {const marquees = document.querySelectorAll('.marquee');marquees.forEach(marquee => {marquee.classList.remove('marquee-fast', 'marquee-slow');if (speed === 'fast') {marquee.classList.add('marquee-fast');} else if (speed === 'slow') {marquees.classList.add('marquee-slow');}});
}</code></pre></div><div class="code-example"><div class="code-header"><div class="code-title">CSS 速度类定义</div><button class="copy-btn" onclick="copyCode(this)">复制代码</button></div><pre><code>.marquee-fast {animation-duration: 15s;
}.marquee-slow {animation-duration: 30s;
}.marquee-reverse {animation-direction: reverse;
}</code></pre></div></div></section><section class="section fade-in"><h2>应用场景</h2><div class="explanation"><p>CSS跑马灯效果可以在多种场景下使用:</p><div class="features"><div class="feature-card"><div class="feature-icon"><i class="fas fa-newspaper"></i></div><div class="feature-title">新闻头条</div><p>用于展示重要新闻或公告,吸引用户注意力</p></div><div class="feature-card"><div class="feature-icon"><i class="fas fa-shopping-cart"></i></div><div class="feature-title">产品展示</div><p>在电商网站中展示热门产品或促销信息</p></div><div class="feature-card"><div class="feature-icon"><i class="fas fa-award"></i></div><div class="feature-title">荣誉展示</div><p>展示企业荣誉、合作伙伴或客户评价</p></div><div class="feature-card"><div class="feature-icon"><i class="fas fa-images"></i></div><div class="feature-title">图片画廊</div><p>创建动态图片展示效果,增强视觉吸引力</p></div></div><div class="note"><p><strong>最佳实践:</strong> 在使用跑马灯效果时,确保内容简洁明了,滚动速度适中,避免给用户带来不适的体验。同时提供暂停功能,方便用户仔细阅读内容。</p></div></div></section></div><footer><p>CSS 跑马灯效果示例 © 2023 | 使用纯CSS实现,无需JavaScript</p></footer><script>function changeSpeed(speed) {const marquees = document.querySelectorAll('.marquee');// 更新按钮状态document.getElementById('speed-fast').classList.remove('active');document.getElementById('speed-normal').classList.remove('active');document.getElementById('speed-slow').classList.remove('active');document.getElementById(`speed-${speed}`).classList.add('active');marquees.forEach(marquee => {marquee.classList.remove('marquee-fast', 'marquee-slow');if (speed === 'fast') {marquee.classList.add('marquee-fast');} else if (speed === 'slow') {marquee.classList.add('marquee-slow');}});}function toggleAnimation() {const marquees = document.querySelectorAll('.marquee');const button = document.getElementById('toggle-btn');const icon = button.querySelector('i');let isPaused = false;marquees.forEach(marquee => {if (marquee.style.animationPlayState === 'paused') {marquee.style.animationPlayState = 'running';icon.className = 'fas fa-pause';button.innerHTML = '<i class="fas fa-pause"></i> 暂停所有动画';} else {marquee.style.animationPlayState = 'paused';icon.className = 'fas fa-play';button.innerHTML = '<i class="fas fa-play"></i> 播放所有动画';isPaused = true;}});if (isPaused) {button.innerHTML = '<i class="fas fa-play"></i> 播放所有动画';}}function copyCode(button) {const codeElement = button.closest('.code-example').querySelector('code');const textArea = document.createElement('textarea');textArea.value = codeElement.textContent;document.body.appendChild(textArea);textArea.select();document.execCommand('copy');document.body.removeChild(textArea);// 显示复制成功提示const originalText = button.textContent;button.textContent = '已复制!';setTimeout(() => {button.textContent = originalText;}, 2000);}// 添加滚动动画const observerOptions = {threshold: 0.1,rootMargin: '0px 0px -50px 0px'};const observer = new IntersectionObserver((entries) => {entries.forEach(entry => {if (entry.isIntersecting) {entry.target.classList.add('fade-in');}});}, observerOptions);document.querySelectorAll('.section').forEach(section => {observer.observe(section);});</script>
</body>
</html>实现原理
创建动画关键帧
使用@keyframes定义从0%到100%的动画过程,通过transform: translateX(-50%)实现元素向左移动50%的宽度。
CSS 动画关键帧
@keyframes marquee {0% {transform: translateX(0);}100% {transform: translateX(-50%);}
}应用动画到元素
将动画应用到跑马灯元素,设置无限循环和线性时间函数。
.marquee {display: flex;width: max-content;animation: marquee 20s linear infinite;
}实现悬停暂停
通过:hover伪类和animation-play-state属性实现悬停时暂停动画。
.marquee:hover {animation-play-state: paused;
}实现无缝滚动
通过复制内容实现无缝滚动效果。当内容滚动到一半时,原始内容开始处刚好接上。
<div class="marquee"><span>内容1</span><span>内容2</span><span>内容3</span><!-- 重复内容实现无缝滚动 --><span>内容1</span><span>内容2</span><span>内容3</span>
</div>技术要点: 为了实现无缝滚动,需要复制一份内容(或使内容足够长),这样当内容滚动到一半时,原始内容开始处刚好接上,形成无缝循环效果。
JavaScript 控制功能
通过JavaScript动态修改CSS类来实现速度控制功能。
function changeSpeed(speed) {const marquees = document.querySelectorAll('.marquee');marquees.forEach(marquee => {marquee.classList.remove('marquee-fast', 'marquee-slow');if (speed === 'fast') {marquee.classList.add('marquee-fast');} else if (speed === 'slow') {marquees.classList.add('marquee-slow');}});
}CSS 速度类定义
.marquee-fast {animation-duration: 15s;
}.marquee-slow {animation-duration: 30s;
}.marquee-reverse {animation-direction: reverse;
}使用到的技术点
1. CSS 动画技术
@keyframes 关键帧动画
定义动画从0%到100%的过程
使用transform: translateX(-50%)实现水平移动
animation 属性
animation: marquee 20s linear infinite- 设置动画名称、时长、时间函数和循环次数animation-play-state: paused- 控制动画播放状态animation-direction: reverse- 反向播放动画
2. CSS 布局技术
Flexbox 布局
display: flex- 创建弹性容器width: max-content- 使容器宽度适应内容
CSS Grid 布局
用于特性展示区域的响应式网格布局
定位技术
position: relative/absolute- 相对和绝对定位伪元素(::before, ::after)创建渐变遮罩
3. 现代 CSS 特性
CSS 自定义属性 (CSS Variables)
定义主题颜色、动画速度等可复用值
CSS 渐变
linear-gradient()- 创建背景渐变和文本渐变效果
backdrop-filter
创建毛玻璃效果
object-fit
控制图片在容器中的填充方式
4. 响应式设计
媒体查询 (@media)
针对不同屏幕尺寸调整样式
相对单位
使用rem、百分比等相对单位
flex-wrap
控制元素在空间不足时的换行行为
5. JavaScript 交互
DOM 操作
querySelectorAll()- 选择多个元素classList.add/remove()- 动态添加/移除CSS类
事件处理
onclick- 按钮点击事件onhover- 鼠标悬停事件(通过CSS实现)
Intersection Observer API
实现滚动时的淡入动画效果
6. 视觉效果技术
transform 变换
scale()- 缩放效果translateX/Y()- 平移效果
transition 过渡
创建平滑的状态变化
box-shadow
添加阴影效果增强立体感
text-shadow
文字阴影效果
注意事项
1. 性能优化
使用 transform 和 opacity
这些属性不会触发重排,动画性能更好
避免使用会触发重排的属性(如width、height、left、top)
硬件加速
transform和opacity属性可以利用GPU加速
动画复杂度
保持动画简单,避免过多复杂的动画同时运行
2. 可访问性
动画暂停功能
必须提供暂停动画的方法(如悬停暂停)
考虑前庭障碍用户,避免引起不适
键盘导航
确保所有功能可以通过键盘操作
屏幕阅读器
使用适当的ARIA标签和语义化HTML
3. 浏览器兼容性
前缀使用
某些CSS属性可能需要浏览器前缀(-webkit-, -moz-, -ms-)
渐进增强
在不支持某些特性的浏览器中提供降级方案
功能检测
使用@supports规则检测CSS特性支持
4. 用户体验
动画速度
速度不宜过快,确保内容可读
提供速度调节选项
暂停时机
用户与内容交互时应暂停动画
页面不可见时(如标签页切换)应暂停动画
内容重要性
跑马灯内容不应是关键信息,用户可能错过
5. 内容设计
无缝循环
确保内容复制足够形成无缝循环
计算合适的动画时长和内容长度比例
响应式内容
在不同屏幕尺寸下调整内容大小和布局
移动设备上可能需要简化内容
6. 代码维护
CSS 组织
使用CSS变量统一管理颜色、尺寸等
合理分组相关样式
命名规范
使用有意义的类名和ID
遵循BEM或其他命名约定
注释和文档
为复杂代码添加详细注释
提供使用说明和示例
7. 移动端优化
触摸交互
考虑触摸设备上的交互方式
确保按钮和交互元素有足够的触摸目标大小
性能考虑
移动设备性能有限,优化动画复杂度
考虑在低端设备上减少动画效果
8. 无障碍设计
减少运动
提供减少动画的选项(如通过 prefers-reduced-motion 媒体查询)
焦点管理
确保焦点在交互过程中正确移动
语义化结构
使用恰当的HTML标签传达内容结构
最佳实践总结
性能优先:优先使用transform和opacity实现动画
用户控制:始终提供暂停和速度控制选项
渐进增强:在不支持某些特性的浏览器中提供可用的降级方案
响应式设计:确保在所有设备上都有良好的体验
无障碍访问:考虑所有用户的需求,包括有特殊需求的用户
内容适宜:跑马灯适合展示非关键信息,重要内容应有静态展示方式
伪代码
页面结构
<div class="image-marquee__group image-marquee__hover">{{#for _ in 1 | range(4)}}<div style="--animation-time: {{block.settings.select_speed}}s;"class="image-marquee__item {{#if block.settings.select_direction == '1'}}image-marquee-reverse{{/if}}"><div style="{{#if block.settings.switch_bgColor}}border-radius:{{block.settings.range_radius}}px;background-color:rgba({{block.settings.color_bgColor.red}},{{block.settings.color_bgColor.green}},{{block.settings.color_bgColor.blue}},{{block.settings.range_mask}}%);{{/if}}"class="image-marquee__text" >{{{block.settings.text}}}</div><div style="width: {{block.settings.range_height}}px;"class="image-marquee__image">{{#if block.settings.image}}{{#component "image" data=block.settings.image /}}{{#else/}}{{#placeholder_svg "image" class="empty-image-class" /}}{{/if}}</div><div style="{{#if block.settings.switch_bgColor}}border-radius:{{block.settings.range_radius}}px;background-color:rgba({{block.settings.color_bgColor.red}},{{block.settings.color_bgColor.green}},{{block.settings.color_bgColor.blue}},{{block.settings.range_mask}}%);{{/if}}"class="image-marquee__text">{{{block.settings.text}}}</div><div style="width: {{block.settings.range_height}}px;"class="image-marquee__image" {{{block.shopline_attributes}}}>{{#if block.settings.image}}{{#component "image" data=block.settings.image /}}{{#else/}}{{#placeholder_svg "image" class="empty-image-class" /}}{{/if}}</div></div>{{/for}}
</div>样式动画
.image-marquee-wrap {display: flex;align-items: center;overflow: hidden;width: 100%;
}.image-marquee__group{font-size: 36px;font-weight: bold;color: #232833;width: max-content;display: flex;align-items: center;}.image-marquee__item{display: flex;align-items: center;white-space: nowrap;width: fit-content;// 动画animation: move var(--animation-time) linear infinite;
}.image-marquee__text{color: rgb(var(--color-text));
}
// 反向
.image-marquee-reverse {animation-direction: reverse;
}
// 暂停
.image-marquee__hover:hover .image-marquee__item{animation-play-state: paused;
}@keyframes move {/* 0% {transform: translateZ(0)}to {transform: translate3d(-100%,0,0)} */0% {transform: translateX(0);}100% {transform: translateX(-50%);}
}