使用 CSS @keyframes 动画(推荐,最常用)

这是最简单、性能最好且最常用的方法,它完全使用CSS实现,无需JavaScript,非常适合制作无缝循环的图片轮播。

html网页上连续滚动图片的制作
(图片来源网络,侵删)

核心思路:

  1. 容器:创建一个固定宽度和高度的容器,并设置 overflow: hidden 来隐藏超出部分的图片。
  2. 图片列表:将所有图片放在一个 <div> 中,这个 <div> 的宽度是所有图片宽度之和。
  3. 动画:使用CSS @keyframes 创建一个从左到右的平移动画,动画结束时,图片列表的位置会回到起点,但由于我们复制了第一张图片,所以看起来是连续的。

实现步骤:

HTML 结构

我们需要一个容器 .scroll-container,里面包含一个图片列表 .scroll-content,为了实现无缝循环,图片列表的第一张图片需要被复制并添加到列表的末尾

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">CSS 连续滚动图片</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <h1>横向连续滚动图片展示</h1>
    <div class="scroll-container">
        <!-- 图片列表 -->
        <div class="scroll-content">
            <!-- 原始图片 -->
            <img src="https://picsum.photos/seed/img1/300/200.jpg" alt="图片 1">
            <img src="https://picsum.photos/seed/img2/300/200.jpg" alt="图片 2">
            <img src="https://picsum.photos/seed/img3/300/200.jpg" alt="图片 3">
            <img src="https://picsum.photos/seed/img4/300/200.jpg" alt="图片 4">
            <img src="https://picsum.photos/seed/img5/300/200.jpg" alt="图片 5">
            <!-- 为了无缝循环,将第一张图片复制一份放在最后 -->
            <img src="https://picsum.photos/seed/img1/300/200.jpg" alt="图片 1 (副本)">
        </div>
    </div>
</body>
</html>

CSS 样式

这是实现滚动的关键。

html网页上连续滚动图片的制作
(图片来源网络,侵删)
/* style.css */
/* 基础样式 */
body {
    font-family: sans-serif;
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 20px;
}
h1 {
    color: #333;
}
/* 1. 滚动容器 */
.scroll-container {
    width: 800px; /* 容器宽度 */
    height: 220px; /* 容器高度,比图片高一点 */
    overflow: hidden; /* 关键:隐藏超出容器的部分 */
    border: 1px solid #ccc;
    border-radius: 8px;
    box-shadow: 0 4px 8px rgba(0,0,0,0.1);
    position: relative; /* 为内部动画提供定位上下文 */
}
/* 2. 图片列表 */
.scroll-content {
    display: flex; /* 使用 Flexbox 布局,让图片水平排列 */
    width: calc(300px * 6); /* 关键:宽度为所有图片宽度之和 (5张原始 + 1张副本) */
    animation: scroll 20s linear infinite; /* 关键:应用动画 */
}
/* 3. 单张图片样式 */
.scroll-content img {
    width: 300px;
    height: 200px;
    object-fit: cover; /* 保证图片不变形 */
    flex-shrink: 0; /* 防止图片被压缩 */
}
/* 4. 核心动画定义 */
@keyframes scroll {
    0% {
        transform: translateX(0); /* 初始位置,第一张图片在容器最左边 */
    }
    100% {
        /* 关键:动画结束位置,将图片列表向左移动,直到第一张图片的副本完全进入容器,
           同时原始的第一张图片完全移出容器左侧,移动距离就是一张图片的宽度。 */
        transform: translateX(-300px); 
    }
}
/* 鼠标悬停时暂停滚动 */
.scroll-container:hover .scroll-content {
    animation-play-state: paused;
}

原理详解:

  • overflow: hidden:这是实现“视口”效果的核心,它告诉浏览器,.scroll-container 内部的任何超出其范围的内容都不要显示。
  • display: flex:让所有 <img> 标签在同一行内水平排列。
  • animation: scroll 20s linear infinite
    • scroll:我们定义的动画名称。
    • 20s:动画持续20秒,你可以根据需要调整。
    • linear:动画速度是均匀的。
    • infinite:动画无限次循环播放。
  • transform: translateX(-300px):这是动画的终点,它将整个图片列表向左平移了 300px(即一张图片的宽度),因为我们在末尾添加了第一张图片的副本,所以当动画执行到这里时,用户看到的是第二张图片无缝地接在了第一张图片的后面,而整个列表又回到了初始位置,等待下一次动画。

使用 JavaScript(更灵活)

如果滚动效果需要更复杂的控制(比如鼠标悬停暂停、点击切换、响应式调整速度等),使用JavaScript会是更好的选择。

核心思路:

  1. 获取图片列表元素。
  2. 使用 setInterval 定期更新图片列表的 transform: translateX 属性,实现平滑移动。
  3. 当滚动到末尾(即第一张图片完全移出视口)时,瞬间将图片列表的位置重置到起点,并移除第一张图片的副本,然后将它追加到末尾,实现无缝循环。

实现代码:

HTML 结构 (与方法一类似,但不需要在HTML中手动添加副本)

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">JS 连续滚动图片</title>
    <style>
        /* CSS 基本样式与方法一相同,但移除 animation 相关代码 */
        body { font-family: sans-serif; display: flex; flex-direction: column; align-items: center; padding: 20px; }
        h1 { color: #333; }
        .scroll-container {
            width: 800px;
            height: 220px;
            overflow: hidden;
            border: 1px solid #ccc;
            border-radius: 8px;
            box-shadow: 0 4px 8px rgba(0,0,0,0.1);
        }
        .scroll-content {
            display: flex;
            transition: transform 0.5s ease-in-out; /* 添加平滑过渡效果 */
        }
        .scroll-content img {
            width: 300px;
            height: 200px;
            object-fit: cover;
            flex-shrink: 0;
        }
    </style>
</head>
<body>
    <h1>JS 控制的连续滚动图片</h1>
    <div class="scroll-container" id="js-scroll-container">
        <div class="scroll-content" id="js-scroll-content">
            <img src="https://picsum.photos/seed/js1/300/200.jpg" alt="图片 1">
            <img src="https://picsum.photos/seed/js2/300/200.jpg" alt="图片 2">
            <img src="https://picsum.photos/seed/js3/300/200.jpg" alt="图片 3">
            <img src="https://picsum.photos/seed/js4/300/200.jpg" alt="图片 4">
            <img src="https://picsum.photos/seed/js5/300/200.jpg" alt="图片 5">
        </div>
    </div>
    <script src="script.js"></script>
</body>
</html>

JavaScript 代码

// script.js
document.addEventListener('DOMContentLoaded', () => {
    const container = document.getElementById('js-scroll-container');
    const content = document.getElementById('js-scroll-content');
    const images = content.getElementsByTagName('img');
    const imageWidth = images[0].clientWidth; // 获取第一张图片的宽度
    let position = 0;
    let animationId;
    // 克隆第一张图片并添加到列表末尾,用于无缝循环
    const firstImageClone = images[0].cloneNode(true);
    content.appendChild(firstImageClone);
    function startScrolling() {
        // 使用 requestAnimationFrame 实现更流畅的动画
        function scroll() {
            position -= 1; // 每次向左移动1像素
            content.style.transform = `translateX(${position}px)`;
            // 检查是否滚动到第一张图片完全离开视口的位置
            if (position <= -imageWidth) {
                // 瞬间重置位置,但用户无感知
                position += imageWidth;
                // 将第一张图片移到末尾
                content.style.transition = 'none'; // 禁用过渡效果,实现瞬间移动
                content.style.transform = `translateX(${position}px)`;
                // 强制浏览器重绘,然后恢复过渡效果
                void content.offsetWidth; 
                content.style.transition = 'transform 0.5s ease-in-out';
                // 移除第一张原始图片,并将其副本追加到末尾
                content.removeChild(images[0]);
                content.appendChild(images[0].cloneNode(true));
            }
            animationId = requestAnimationFrame(scroll);
        }
        scroll();
    }
    // 鼠标悬停时暂停
    container.addEventListener('mouseenter', () => {
        cancelAnimationFrame(animationId);
    });
    // 鼠标离开时继续
    container.addEventListener('mouseleave', () => {
        startScrolling();
    });
    // 开始滚动
    startScrolling();
});

使用现成的库(最快,最功能强大)

在实际项目中,我们通常会使用成熟的轮播图库,它们经过充分优化,功能强大且易于使用。

html网页上连续滚动图片的制作
(图片来源网络,侵删)

推荐库:

  • Swiper.js: 功能最全面,性能优异,支持触摸滑动、无限循环、分页器、导航按钮等几乎所有你能想到的功能。
  • Slick: 非常流行,配置简单,效果炫酷。

使用 Swiper.js 的示例:

引入 Swiper 的 CSS 和 JS 文件

<!-- Swiper CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.css"/>
<!-- Swiper JS -->
<script src="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.js"></script>

HTML 结构

Swiper 有固定的HTML结构,你需要遵循它。

<div class="swiper mySwiper">
    <div class="swiper-wrapper">
        <!-- Slide 1 -->
        <div class="swiper-slide">
            <img src="https://picsum.photos/seed/swiper1/800/400.jpg" alt="Slide 1">
        </div>
        <!-- Slide 2 -->
        <div class="swiper-slide">
            <img src="https://picsum.photos/seed/swiper2/800/400.jpg" alt="Slide 2">
        </div>
        <!-- Slide 3 -->
        <div class="swiper-slide">
            <img src="https://picsum.photos/seed/swiper3/800/400.jpg" alt="Slide 3">
        </div>
        <!-- ... more slides ... -->
    </div>
    <!-- 如果需要分页器 -->
    <div class="swiper-pagination"></div>
</div>

初始化 Swiper

<script> 标签中初始化你的轮播图。

<script>
    document.addEventListener('DOMContentLoaded', () => {
        var swiper = new Swiper(".mySwiper", {
            loop: true, // 无限循环模式
            autoplay: {
                delay: 2500, // 自动切换时间
                disableOnInteraction: false, // 用户操作后是否停止自动播放
            },
            pagination: {
                el: ".swiper-pagination", // 分页器的选择器
                clickable: true, // 点击分页器切换
            },
        });
    });
</script>

总结与选择建议

方法 优点 缺点 适用场景
CSS @keyframes 性能最好,代码简单,纯CSS实现,无依赖。 动画控制简单(如暂停/播放),逻辑固定,需要手动处理副本。 简单的、不需要交互的图片轮播或新闻滚动条。
JavaScript 非常灵活,可以添加任意复杂的交互逻辑,动态控制。 代码量稍多,需要手动处理DOM操作和动画逻辑。 需要复杂控制、响应式行为或与后端数据结合的场景。
轮播图库 (Swiper) 功能强大,开箱即用,效果专业,支持触摸、响应式等。 引入了外部依赖,会增加页面体积。 商业项目、复杂的轮播需求、追求开发效率和用户体验的场景。

对于大多数情况,我首推使用方法一(CSS动画),因为它简单、高效且足够满足基本需求,如果项目需要更高级的功能,再考虑使用方法二(JS)或直接集成方法三(库)。