progress 的 value 和 max 必须为数字且 value ≤ max,max 默认为1,动态更新应直接赋值而非 setattribute,并需用 css 伪元素适配各浏览器。

progress 标签的 value 和 max 必须是数字,且 value ≤ max
浏览器会直接忽略非数值的 value 或 max,比如写成 value="50%" 或 max="100"(带引号但值是字符串)——看似合法,实则无效,进度条永远显示为 0%。必须确保两个属性都是纯数字,且 value 不超过 max。
常见错误现象:<progress value="75" max="100"></progress> 看似没问题,但如果 value 是 JS 动态插入的字符串(如 el.value = "75"),它就失效了;正确做法是显式转数字:el.value = 75 或 el.setAttribute("value", 75)。
-
max默认是 1,不是 100 —— 这点容易被忽略,设value="80"却没设max,结果进度条满格(因为 80 > 1) - 若只需百分比语义,推荐统一用
max="100",再让value取 0–100 整数,最直观 - 小数也合法:
<progress value="0.75" max="1"></progress>等价于value="75" max="100"
JS 动态更新 progress 时,直接赋值比 setAttribute 更可靠
用 setAttribute 更新 value 会触发 DOM 属性变更,但部分旧版浏览器(如 IE、某些 Android WebView)可能不重绘;而直接赋值给 value 属性(el.value = 42)走的是表单控件的内部逻辑,渲染更及时。
使用场景:轮询接口返回进度、文件上传监听 upload.onprogress、动画帧驱动更新等。
- ✅ 推荐:
const bar = document.querySelector("progress"); bar.value = Math.round(percent); - ❌ 避免:
bar.setAttribute("value", percent.toFixed(0));(字符串值可能被忽略) - 注意:如果
max是动态变化的,也要同步更新bar.max,否则value超出范围会被截断为max
progress 元素默认无样式,CSS 控制外观需区分伪元素
原生 <progress></progress> 在不同浏览器中渲染机制不同,Chrome/Edge 用 ::-webkit-progress-bar 和 ::-webkit-progress-value,Firefox 用 ::moz-progress-bar,Safari 混合支持。不加 CSS 时,它只是个灰底蓝条的极简控件,颜色、高度、圆角全不可控。
性能影响:伪元素选择器层级深、匹配开销略高,但对单个进度条几乎无感;真正要注意的是,不要在大量 progress 元素上频繁强制重排(比如每 16ms 改 width)。
- 基础兼容写法:
progress { height: 8px; -webkit-appearance: none; appearance: none; } progress::-webkit-progress-bar { background-color: #eee; } progress::-webkit-progress-value { background-color: #007bff; } progress::-moz-progress-bar { background-color: #007bff; } - 若需自定义背景条渐变或动画,只能靠包裹容器 + 伪元素模拟,原生
progress不支持background-image直接作用于进度部分 - 无障碍提示:记得加
aria-label或关联<label></label>,否则屏幕阅读器可能只读“进度条”,不读当前值
value 为 0 或未设置时,progress 显示“不确定”状态
当 value 缺失、为 0 且 max 有效时,部分浏览器(如 Firefox)仍会显示空进度条;但若 value 完全未设置,或 max 为 0 / NaN,浏览器会退化为“不确定”状态(通常表现为动画条纹,类似 loading spinner)。这不是 bug,而是规范行为。
容易踩的坑:服务端返回进度为 null,JS 直接赋值 bar.value = data.progress,结果 data.progress 是 null → bar.value 变成 0,但视觉上却像在加载——实际是因 max 未设或为 0,触发了不确定模式。
- 安全写法:
if (typeof progress === "number" && progress >= 0) bar.value = Math.min(progress, bar.max || 100); - 初始化时显式设
max:<progress max="100" value="0"></progress>,避免依赖默认值 - 不确定状态无法用 CSS 精确控制动画节奏,如需定制 loading 效果,建议改用
<div> + CSS animation 原生 <code>progress的边界情况多藏在属性类型、浏览器默认值和伪元素兼容性里,而不是功能本身。真要稳定,得盯住三件事:数字类型、max显式设置、CSS 伪元素双端覆盖。











