html横向滚动列表 带进度条

27 阅读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>
			.container {
				width: 80vw;
				margin: 10px auto;
				box-sizing: border-box;
			}

			.list {
				width: 80vw;
				height: 100px;
				display: flex;
				overflow-x: auto;
				scroll-behavior: smooth;
				scrollbar-width: none;
				/* Firefox */
				-ms-overflow-style: none;
				/* IE/Edge */
			}

			.list::-webkit-scrollbar {
				display: none;
				/* Chrome/Safari/Opera */
			}

			.item {
				width: 100px;
				height: 100px;
				background-color: #4CAF50;
				color: white;
				display: flex;
				align-items: center;
				justify-content: center;
				font-size: 18px;
				font-weight: bold;
				flex-shrink: 0;
				border: 1px solid #45a049;
				box-sizing: border-box;
			}

			.item:nth-child(even) {
				background-color: #2196F3;
			}

			.item:nth-child(3n) {
				background-color: #FF9800;
			}

			.progress-container {
				width: 40vw;
				height: 40px;
				margin: 20px auto;
				position: relative;
				background-color: #e0e0e0;
				border-radius: 5px;
				
			}

			.progress-box {
				width: 10vw;
				height: 100%;
				position: absolute;
				left: 0;
				top: 0;
				background-color: #f44336;
				border-radius: 5px;
				transition: left 0.1s ease-out;
			}

			.scroll-indicator {
				text-align: center;
				margin-top: 10px;
				color: #666;
				font-size: 14px;
			}
		</style>
	</head>
	<body>
		<div class="container">
			<div class="list" id="listContainer">
				<div class="item">Item 1</div>
				<div class="item">Item 2</div>
				<div class="item">Item 3</div>
				<div class="item">Item 4</div>
				<div class="item">Item 5</div>
				<div class="item">Item 6</div>
				<div class="item">Item 7</div>
				<div class="item">Item 8</div>
				<div class="item">Item 9</div>
				<div class="item">Item 10</div>
			</div>

			<div class="progress-container" id="progressContainer">
				<div class="progress-box" id="progressBox"></div>
			</div>

			<div class="scroll-indicator">
				横向滚动上方列表查看进度条变化
			</div>
		</div>

		<script>
			document.addEventListener('DOMContentLoaded', function() {
				const listContainer = document.getElementById('listContainer');
				const progressBox = document.getElementById('progressBox');
				const progressContainer = document.getElementById('progressContainer');
		
				// 设置进度条容器的宽度
				const containerWidth = progressContainer.offsetWidth;
				const progressBarWidth = progressBox.offsetWidth;
				const maxScrollLeft = listContainer.scrollWidth - listContainer.offsetWidth; // 总可滚动距离

				// 监听滚动事件
				listContainer.addEventListener('scroll', function() {
					// 计算滚动比例 (0 到 1)
					const scrollRatio = listContainer.scrollLeft / maxScrollLeft;

					// 计算进度条应移动的距离
					// 进度条的最大移动距离是容器宽度减去自身宽度
					const maxProgressMove = containerWidth - progressBarWidth;
					const progressPosition = scrollRatio * maxProgressMove;

					// 应用位置
					progressBox.style.left = `${progressPosition}px`;
				});

				// 初始化进度条位置
				progressBox.style.left = '0px';
			});
		</script>
	</body>
</html>

效果 在这里插入图片描述 这段 HTML + CSS + JavaScript 代码实现了一个 横向滚动列表,并配合一个 水平进度条 来反映用户滚动的位置。下面从整体结构和核心逻辑两个方面进行解释。


🧩 整体结构说明

1. HTML 结构

  • .list:一个横向可滚动的容器,包含多个 .item 元素(共10个)。
  • .progress-container:一个固定宽度的灰色背景容器,用于显示进度条。
  • .progress-box:红色小方块,作为“进度指示器”,会随着滚动位置左右移动。

2. CSS 样式重点

  • .list 设置了 overflow-x: autoscroll-behavior: smooth,使其可以横向平滑滚动,并隐藏滚动条(通过各浏览器兼容写法)。
  • .item 使用 flex-shrink: 0 确保不会被压缩,保持固定宽度。
  • .progress-box 使用 position: absolute 定位在 .progress-container 内部,通过修改 left 值来移动。

⚙️ 核心逻辑解析(JavaScript 部分)

1. 获取关键 DOM 元素

const listContainer = document.getElementById('listContainer');
const progressBox = document.getElementById('progressBox');
const progressContainer = document.getElementById('progressContainer');

2. 计算基础尺寸

const containerWidth = progressContainer.offsetWidth;        // 进度条容器宽度(例如 40vw)
const progressBarWidth = progressBox.offsetWidth;           // 进度条自身宽度(例如 10vw)
const maxScrollLeft = listContainer.scrollWidth - listContainer.offsetWidth;
  • maxScrollLeft 是列表最多能向右滚动的距离(总内容宽度 - 可视区域宽度)。

3. 监听滚动事件

listContainer.addEventListener('scroll', function() {
    const scrollRatio = listContainer.scrollLeft / maxScrollLeft;
    const maxProgressMove = containerWidth - progressBarWidth;
    const progressPosition = scrollRatio * maxProgressMove;
    progressBox.style.left = `${progressPosition}px`;
});

🔍 关键公式:

  • 滚动比例
    scrollRatio = 当前滚动距离 / 最大可滚动距离
    → 范围是 0 ~ 1(未滚动到滚到底)。

  • 进度条最大移动距离
    maxProgressMove = 容器宽度 - 进度条自身宽度
    → 因为进度条不能移出容器右边。

  • 进度条当前位置
    progressPosition = scrollRatio × maxProgressMove
    → 将滚动比例映射到进度条的移动范围。

✅ 这样就实现了:滚动列表时,红色进度条同步平滑移动,反映当前滚动进度

4. 初始化位置

progressBox.style.left = '0px';

确保页面加载时进度条在最左侧(对应未滚动状态)。


🎯 总结:核心思想

将横向滚动的“相对进度”(0% ~ 100%)线性映射到进度条在容器内的“绝对位置”

这种模式常用于:

  • 指示长内容的阅读/浏览进度
  • UI 中的导航辅助(如故事流、商品轮播)
  • 增强用户对可滚动区域长度的感知