当前位置: 首页 > news >正文

告别marquee!用CSS+JS实现现代无缝循环滚动(附完整代码)

告别marquee!用CSS+JS实现现代无缝循环滚动(附完整代码)

在网页设计中,循环滚动效果常用于展示新闻、公告、产品列表等内容。虽然传统的<marquee>标签简单易用,但它早已被W3C列为过时标签,存在性能低下、兼容性差、缺乏灵活性等问题。本文将介绍如何利用现代CSS动画结合JavaScript克隆技术,实现高性能、可定制化的无缝循环滚动效果。

1. 为什么应该放弃marquee标签

<marquee>是HTML早期引入的一个非标准标签,虽然它能够快速实现文字滚动效果,但在现代前端开发中存在诸多问题:

  • 兼容性问题:HTML5规范已明确不推荐使用marquee,部分浏览器可能不支持某些属性
  • 性能瓶颈:marquee的滚动实现方式会导致不必要的重绘和回流
  • 可控性差:难以精确控制滚动速度、暂停时机等细节
  • 可访问性差:屏幕阅读器可能无法正确识别marquee中的内容
  • 样式限制:难以与现代CSS框架和设计系统集成
<!-- 过时的marquee示例 --> <marquee direction="left" scrollamount="5"> 这是一条使用marquee标签实现的滚动文字 </marquee>

2. CSS动画基础实现方案

使用CSS动画是实现循环滚动的首选方案,它能够利用浏览器的硬件加速,提供更流畅的性能表现。

2.1 水平无缝滚动实现

<div class="scroll-container"> <div class="scroll-content"> <span>内容项1</span> <span>内容项2</span> <span>内容项3</span> </div> </div>
.scroll-container { width: 100%; overflow: hidden; white-space: nowrap; position: relative; } .scroll-content { display: inline-block; animation: scroll 10s linear infinite; } @keyframes scroll { 0% { transform: translateX(0); } 100% { transform: translateX(-100%); } }

2.2 垂直无缝滚动实现

.scroll-container { height: 200px; overflow: hidden; position: relative; } .scroll-content { animation: scroll-vertical 10s linear infinite; } @keyframes scroll-vertical { 0% { transform: translateY(0); } 100% { transform: translateY(-100%); } }

提示:纯CSS方案虽然简单,但存在内容不足时会出现空白区域的问题。接下来我们将介绍如何通过JavaScript解决这个问题。

3. 结合JavaScript的完美解决方案

为了实现真正的无缝循环滚动效果,我们需要使用JavaScript动态克隆内容节点,确保滚动内容足够填充整个滚动区域。

3.1 基本实现原理

  1. 获取原始内容节点
  2. 克隆内容节点并追加到容器中
  3. 使用CSS动画实现滚动效果
  4. 当动画结束时重置位置并重新开始
function setupInfiniteScroll(containerSelector, contentSelector) { const container = document.querySelector(containerSelector); const content = document.querySelector(contentSelector); // 克隆内容以实现无缝循环 const clone = content.cloneNode(true); container.appendChild(clone); // 设置动画 content.style.animation = `scroll ${content.children.length * 2}s linear infinite`; } // 使用示例 setupInfiniteScroll('.scroll-container', '.scroll-content');

3.2 完整实现代码

<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>现代无缝滚动实现</title> <style> .scroll-container { width: 100%; overflow: hidden; white-space: nowrap; position: relative; border: 1px solid #eee; padding: 10px 0; } .scroll-content { display: inline-flex; animation: scroll 20s linear infinite; } .scroll-content span { padding: 0 20px; font-size: 16px; color: #333; } @keyframes scroll { 0% { transform: translateX(0); } 100% { transform: translateX(-50%); } } </style> </head> <body> <div class="scroll-container"> <div class="scroll-content"> <span>最新公告:系统将于今晚24:00进行维护升级</span> <span>新品上市:全新一代产品现已发布</span> <span>限时优惠:全场商品8折起</span> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { const container = document.querySelector('.scroll-container'); const content = document.querySelector('.scroll-content'); // 计算内容总宽度 const contentWidth = Array.from(content.children).reduce( (total, child) => total + child.offsetWidth, 0 ); // 如果内容宽度不足容器宽度,克隆内容直到填满 if (contentWidth < container.offsetWidth) { const clonesNeeded = Math.ceil(container.offsetWidth / contentWidth) + 1; for (let i = 1; i < clonesNeeded; i++) { container.appendChild(content.cloneNode(true)); } } else { // 否则只克隆一次实现无缝循环 container.appendChild(content.cloneNode(true)); } // 动态设置动画时间 content.style.animationDuration = `${contentWidth / 50}s`; }); </script> </body> </html>

4. 高级功能与优化技巧

4.1 响应式处理

为了使滚动效果在不同屏幕尺寸下都能正常工作,我们需要添加响应式处理:

function handleResize() { const container = document.querySelector('.scroll-container'); const content = document.querySelector('.scroll-content'); // 移除所有克隆节点 const clones = document.querySelectorAll('.scroll-content:not(:first-child)'); clones.forEach(clone => clone.remove()); // 重新计算并添加克隆 const contentWidth = Array.from(content.children).reduce( (total, child) => total + child.offsetWidth, 0 ); if (contentWidth < container.offsetWidth) { const clonesNeeded = Math.ceil(container.offsetWidth / contentWidth) + 1; for (let i = 1; i < clonesNeeded; i++) { container.appendChild(content.cloneNode(true)); } } else { container.appendChild(content.cloneNode(true)); } // 更新动画时间 content.style.animationDuration = `${contentWidth / 50}s`; } // 监听窗口大小变化 window.addEventListener('resize', handleResize);

4.2 鼠标悬停暂停功能

const container = document.querySelector('.scroll-container'); const content = document.querySelector('.scroll-content'); container.addEventListener('mouseenter', () => { content.style.animationPlayState = 'paused'; }); container.addEventListener('mouseleave', () => { content.style.animationPlayState = 'running'; });

4.3 性能优化建议

  1. 使用will-change属性:提前告知浏览器哪些属性会变化

    .scroll-content { will-change: transform; }
  2. 减少重绘:确保滚动内容不会导致布局变化

  3. 适当使用requestAnimationFrame:对于需要精细控制的动画

  4. 避免过多克隆:只克隆必要的节点数量

// 优化后的克隆逻辑 const containerWidth = container.offsetWidth; const contentWidth = Array.from(content.children).reduce( (total, child) => total + child.offsetWidth, 0 ); // 计算需要克隆的次数 const clonesNeeded = contentWidth < containerWidth ? Math.ceil(containerWidth / contentWidth) : 1; // 移除多余的克隆 const existingClones = document.querySelectorAll('.scroll-content:not(:first-child)'); existingClones.forEach((clone, index) => { if (index >= clonesNeeded - 1) clone.remove(); }); // 添加不足的克隆 for (let i = existingClones.length; i < clonesNeeded; i++) { container.appendChild(content.cloneNode(true)); }

5. 实际应用案例与变体

5.1 新闻跑马灯效果

<div class="news-ticker"> <div class="ticker-content"> <span class="ticker-item">Breaking: 重大科技突破</span> <span class="ticker-item">财经: 股市今日大涨</span> <span class="ticker-item">体育: 国家队获得冠军</span> </div> </div> <style> .news-ticker { background: #333; color: white; padding: 10px; overflow: hidden; } .ticker-content { display: inline-flex; animation: ticker-scroll 30s linear infinite; } .ticker-item { padding: 0 40px; position: relative; } .ticker-item:after { content: "•"; position: absolute; right: 10px; color: #666; } @keyframes ticker-scroll { 0% { transform: translateX(0); } 100% { transform: translateX(-50%); } } </style>

5.2 产品轮播展示

<div class="product-carousel"> <div class="product-track"> <div class="product-card">产品1</div> <div class="product-card">产品2</div> <div class="product-card">产品3</div> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { const track = document.querySelector('.product-track'); const cards = document.querySelectorAll('.product-card'); const cardWidth = cards[0].offsetWidth; // 计算需要克隆的数量 const visibleCards = Math.ceil(window.innerWidth / cardWidth); for (let i = 0; i < visibleCards; i++) { cards.forEach(card => { track.appendChild(card.cloneNode(true)); }); } // 设置动画 track.style.animation = `carousel-scroll ${cards.length * 3}s linear infinite`; }); </script>

5.3 垂直公告栏实现

<div class="announcement-vertical"> <ul class="announcement-list"> <li>公告1: 系统维护通知</li> <li>公告2: 新功能上线</li> <li>公告3: 用户反馈收集</li> </ul> </div> <style> .announcement-vertical { height: 200px; overflow: hidden; position: relative; border: 1px solid #ddd; } .announcement-list { animation: vertical-scroll 15s linear infinite; } @keyframes vertical-scroll { 0% { transform: translateY(0); } 100% { transform: translateY(-50%); } } </style> <script> document.addEventListener('DOMContentLoaded', function() { const list = document.querySelector('.announcement-list'); const clone = list.cloneNode(true); list.parentNode.appendChild(clone); }); </script>
http://www.jsqmd.com/news/488459/

相关文章:

  • 番茄小说下载工具全流程解决方案:从内容获取到数字资产管理
  • ROS新手必看:5分钟搞定键盘控制TurtleBot3运动(C++/Python双版本)
  • CCPC 2024哈尔滨站题解精析:从签到到金牌的8道算法实战
  • AssetStudio:Unity资源全流程处理工具,助力开发者高效提取与管理游戏资产
  • HunyuanVideo-Foley惊艳展示:看AI如何为无声视频配上电影级音效
  • 2026年质量好的湿土碎土机厂家推荐:黏性土碎土机推荐公司 - 品牌宣传支持者
  • YOLO-v8.3开箱即用:预置环境助力快速启动缺陷检测项目
  • ECU-TEST实战:如何用模块化思维提升汽车测试效率(含常见配置避坑指南)
  • 地瓜机器人完成1.2亿美元融资:黄浦江资本与高瓴再度加持
  • 阿里CosyVoice2-0.5B惊艳效果展示:真实声音克隆案例分享
  • 实战分享:如何用天地伟业私有协议实现NVR与AS-V1000平台的无缝对接?
  • 5分钟搞定Dify-web镜像构建:用华为云镜像加速你的Docker编译过程
  • OpenWrt磁盘扩容实战:5分钟搞定虚拟机软路由存储不足问题
  • 从数据到设计:ArcMap专题地图的视觉叙事与布局艺术
  • 达梦DSC集群部署踩坑记:NVMe SSD扇区大小不匹配导致的read error解决实录
  • 5G模组信号质量实战:如何用AT指令快速解析RSSI、RSRP、RSRQ和SINR
  • 2026年靠谱的铜陵AI搜索GEO优化公司推荐:铜陵AI搜索GEO优化热门公司推荐 - 品牌宣传支持者
  • 别再混淆了!ggplot2中stat参数的count、bin、identity到底怎么选?附完整代码示例
  • Phi-3-vision-128k-instruct效果可视化:复杂场景图中物体定位+关系推理展示
  • Windows+Ubuntu双系统用户必看:DiskGenius彻底卸载Ubuntu20.04全流程(附EFI分区清理)
  • 一键部署Qwen3-4B:打造属于你的极速、轻量级AI文本助手
  • DAMOYOLO-S模型部署与优化:Java开发者实战指南
  • 自感痕迹:生活即本源
  • 不用PS!用HivisionIDPhotosv1.2.8零代码搞定证件照换底+排版(附避坑指南)
  • Z-Image-GGUF模型参数详解与高级调参技巧:从入门到精通
  • 圣女司幼幽-造相Z-Turbo效果展示:淡金柔光与墨绿长裙的色温协调性分析
  • RAG索引优化实战:用LlamaIndex实现混合搜索+重排的进阶技巧
  • 从SpringCache到JetCache:阿里开源的这些缓存黑科技你真的会用吗?
  • 避坑指南:MCP23017 I2C地址冲突的5种解决方法(附逻辑分析仪截图)
  • Lingbot-Depth-Pretrain-ViTL-14保姆级教程:Ubuntu 20.04系统环境从零部署