progress 进度条
<progress> 是 HTML5 引入的语义化元素,用于表示任务的完成进度。它有两种模式:确定进度(value + max)和不确定进度(无 value)。浏览器会根据这些属性渲染出不同样式的进度条,适用于文件上传、加载状态、任务完成度等场景。
前置知识
阅读本节前,建议先了解:output 输出元素
基础概念
什么是 progress 元素
<progress> 元素表示任务的完成进度。主要特点:
- 语义化:明确表示"进度",屏幕阅读器可识别
- 两种模式:确定进度(显示百分比)和不确定进度(显示加载动画)
- 内置样式:浏览器自动渲染进度条外观
- 属性简单:只需
value和max两个属性
浏览器渲染
不同浏览器对 <progress> 的默认样式有所不同:
| 浏览器 | 外观 |
|---|---|
| Chrome | 绿色进度条(扁条) |
| Firefox | 绿色进度条(较厚) |
| Safari | 灰色进度条 |
| Edge | 蓝色进度条 |
语法
确定进度
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>progress 确定进度</title>
</head>
<body>
<h2>文件上传进度</h2>
<label for="upload">上传进度:</label>
<progress id="upload" value="70" max="100">70%</progress>
<p>已完成 <output for="upload">70</output>%</p>
</body>
</html>不确定进度
当不设置 value 属性时,显示不确定进度动画(表示"正在进行中,但不知道进度"):
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>progress 不确定进度</title>
</head>
<body>
<h2>加载中</h2>
<!-- 不确定进度:无 value 属性 -->
<progress>正在加载...</progress>
<p>数据加载中,请稍候...</p>
</body>
</html>属性说明
| 属性 | 说明 | 默认值 |
|---|---|---|
value | 当前进度值 | 无(不确定进度) |
max | 最大值 | 1 |
form | 关联的表单 ID | 无 |
详细说明
与 output 配合显示百分比
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>progress 百分比</title>
</head>
<body>
<h2>任务进度</h2>
<form>
<label for="task-progress">任务完成度:</label>
<input type="range" id="task-progress" name="progress" min="0" max="100" value="45"
oninput="updateProgress(this.value)">
<progress id="progress-bar" value="45" max="100" style="width: 300px;"></progress>
<output name="percent" for="task-progress">45</output>%
</form>
<script>
function updateProgress(val) {
document.getElementById('progress-bar').value = val;
}
</script>
</body>
</html>JavaScript 动态更新进度
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>progress 动态更新</title>
<style>
body { font-family: sans-serif; max-width: 600px; margin: 40px auto; }
progress { width: 100%; height: 24px; }
.controls { margin: 16px 0; display: flex; gap: 8px; }
button {
padding: 8px 20px;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 14px;
}
.btn-start { background: #4a90d9; color: #fff; }
.btn-reset { background: #ddd; }
</style>
</head>
<body>
<h2>模拟任务进度</h2>
<progress id="my-progress" value="0" max="100"></progress>
<p><output id="progress-text" for="my-progress">0</output>%</p>
<div class="controls">
<button class="btn-start" type="button" id="start-btn">开始</button>
<button class="btn-reset" type="button" id="reset-btn">重置</button>
</div>
<script>
const progressBar = document.getElementById('my-progress');
const progressText = document.getElementById('progress-text');
let timer = null;
document.getElementById('start-btn').addEventListener('click', function () {
let value = parseInt(progressBar.value);
if (timer) clearInterval(timer);
timer = setInterval(() => {
value += Math.floor(Math.random() * 5) + 1;
if (value >= 100) {
value = 100;
clearInterval(timer);
timer = null;
this.textContent = '完成';
this.disabled = true;
}
progressBar.value = value;
progressText.value = value;
}, 200);
});
document.getElementById('reset-btn').addEventListener('click', function () {
clearInterval(timer);
timer = null;
progressBar.value = 0;
progressText.value = 0;
const startBtn = document.getElementById('start-btn');
startBtn.textContent = '开始';
startBtn.disabled = false;
});
</script>
</body>
</html>CSS 自定义样式
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>progress CSS 样式</title>
<style>
body { font-family: sans-serif; max-width: 600px; margin: 40px auto; }
/* 默认样式 */
.progress-default {
width: 100%;
height: 20px;
margin-bottom: 16px;
}
/* 自定义颜色(WebKit/Chrome/Safari/Edge) */
.progress-red {
width: 100%;
height: 24px;
border-radius: 12px;
overflow: hidden;
}
.progress-red::-webkit-progress-bar {
background: #eee;
border-radius: 12px;
}
.progress-red::-webkit-progress-value {
background: linear-gradient(90deg, #e74c3c, #c0392b);
border-radius: 12px;
transition: width 0.3s ease;
}
/* Firefox 自定义 */
.progress-red::-moz-progress-bar {
background: linear-gradient(90deg, #e74c3c, #c0392b);
border-radius: 12px;
}
/* 条纹动画 */
.progress-striped {
width: 100%;
height: 24px;
border-radius: 12px;
overflow: hidden;
}
.progress-striped::-webkit-progress-bar {
background: #ddd;
border-radius: 12px;
}
.progress-striped::-webkit-progress-value {
background: repeating-linear-gradient(
-45deg,
#4a90d9,
#4a90d9 10px,
#357abd 10px,
#357abd 20px
);
border-radius: 12px;
background-size: 28px 28px;
animation: move 0.5s linear infinite;
}
@keyframes move {
0% { background-position: 0 0; }
100% { background-position: 28px 0; }
}
/* 不确定进度动画 */
.progress-indeterminate {
width: 100%;
height: 6px;
}
</style>
</head>
<body>
<h2>自定义进度条样式</h2>
<h3>默认样式</h3>
<progress class="progress-default" value="60" max="100"></progress>
<h3>红色圆角</h3>
<progress class="progress-red" value="75" max="100"></progress>
<h3>条纹动画</h3>
<progress class="progress-striped" value="55" max="100"></progress>
<h3>不确定进度</h3>
<progress class="progress-indeterminate"></progress>
<p>加载中,请稍候...</p>
</body>
</html>实战示例
多任务进度面板
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>多任务进度面板</title>
<style>
body { font-family: sans-serif; max-width: 600px; margin: 40px auto; }
.task {
margin-bottom: 16px;
padding: 12px;
background: #f8f9fa;
border-radius: 8px;
}
.task-header {
display: flex;
justify-content: space-between;
margin-bottom: 8px;
}
.task-name { font-weight: 600; }
.task-percent { color: #4a90d9; font-weight: bold; }
progress { width: 100%; height: 12px; }
</style>
</head>
<body>
<h2>任务进度面板</h2>
<div class="task">
<div class="task-header">
<span class="task-name">文件上传</span>
<span class="task-percent" id="task1-pct">0%</span>
</div>
<progress id="task1" value="0" max="100"></progress>
</div>
<div class="task">
<div class="task-header">
<span class="task-name">数据处理</span>
<span class="task-percent" id="task2-pct">0%</span>
</div>
<progress id="task2" value="0" max="100"></progress>
</div>
<div class="task">
<div class="task-header">
<span class="task-name">生成报告</span>
<span class="task-percent" id="task3-pct">0%</span>
</div>
<progress id="task3" value="0" max="100"></progress>
</div>
<button type="button" id="run-btn" style="padding: 10px 24px; background: #4a90d9; color: #fff; border: none; border-radius: 6px; cursor: pointer;">
开始所有任务
</button>
<script>
document.getElementById('run-btn').addEventListener('click', function () {
this.disabled = true;
// 模拟三个任务
simulateTask('task1', 2000);
setTimeout(() => simulateTask('task2', 3000), 500);
setTimeout(() => simulateTask('task3', 1500), 1000);
});
function simulateTask(id, duration) {
const bar = document.getElementById(id);
const pct = document.getElementById(id + '-pct');
let progress = 0;
const interval = 50;
const timer = setInterval(() => {
progress += Math.random() * 10;
if (progress >= 100) {
progress = 100;
clearInterval(timer);
}
bar.value = Math.min(progress, 100);
pct.textContent = Math.round(bar.value) + '%';
}, interval);
setTimeout(() => {
bar.value = 100;
pct.textContent = '100%';
}, duration);
}
</script>
</body>
</html>注意事项
不用于度量值
<progress> 表示任务进度(0 到 max),不应表示度量值(如磁盘使用率、分数等)。度量值应使用 <meter> 元素。
内容为降级文本
<progress> 标签之间的内容在不支持该元素的浏览器中显示:
html
<!-- 支持 progress 的浏览器显示进度条 -->
<!-- 不支持的浏览器显示 "60%" 文字 -->
<progress value="60" max="100">60%</progress>position 属性
通过 JavaScript 可以读取进度百分比:
javascript
const progress = document.getElementById('my-progress');
console.log(progress.value); // 当前进度值
console.log(progress.max); // 最大值
// position 属性返回 0-1 之间的比率
console.log(progress.position); // 0.6(表示 60%)最佳实践
- 确定 vs 不确定:明确知道进度时使用确定模式,否则使用不确定模式
- 提供文本降级:在标签内放置百分比文本作为降级方案
- 配合 output:使用
<output>显示精确的百分比数字 - 自定义样式:使用 CSS 让进度条与页面风格统一
- 圆角与动画:添加
border-radius和过渡动画提升视觉效果
下一节
继续学习:meter 度量元素