progress-upload 是唯一合理的块名,它准确表达“以进度呈现为核心的上传专用组件”,符合 BEM 原则,支持独立复用、语义清晰、可扩展性强,且与 progress-bar 等通用组件无冲突。

progress-upload 是唯一合理的块名
不能叫 upload-progress 或 file-progress,前者语序倒置(BEM 要求块名是“组件本质”,不是“功能+状态”),后者丢失关键语义——上传进度条和普通进度条(如加载、安装)在交互逻辑、视觉反馈、失败处理上完全不同。progress-upload 明确表达这是一个「以进度呈现为核心的上传专用组件」,且能与 progress-bar 并存而不冲突。
常见错误:uploader__progress 把它降级为 uploader 块的元素,但实际中上传进度条常需独立复用(如弹窗内单独显示、API 调用后手动渲染),它必须是块(Block),不是元素(Element)。
- 不加命名空间(如
form__progress-upload),除非它**永远只嵌在 form 内且样式强耦合表单布局**——这种场景极少,多数项目需要它在拖拽区、API 响应后、甚至 Toast 中复用 - 禁用缩写:
prg-up、up-prog等类名在团队协作中等于无意义字符串,CSS 没有类型系统,缩写无法被工具校验或自动补全 - 不带状态词:
progress-upload--uploading是错的;修饰符应描述变体(--indeterminate)、主题(--dark)或尺寸(--small),而非运行时状态——状态由 JS 控制类增删,不应固化在类名设计里
progress-upload__track 和 progress-upload__fill 必须直属于块
progress-upload__track 是容器轨道,progress-upload__fill 是填充层,二者都必须是 progress-upload 的直接子元素。HTML 中不能出现 <div class="progress-upload"><div class="progress-upload__track"><div class="progress-upload__fill"></div></div></div> 以外的嵌套结构。
容易踩的坑:
立即学习“前端免费学习笔记(深入)”;
- 给
progress-upload__fill设height:它只应通过width(水平)或height(垂直)控制进度比例,高度/宽度必须由__track提供,否则在 Flex/Grid 容器中会破坏对齐 - 在
__fill内再塞图标或文字(如“上传中…”):这已超出进度条职责,应拆成新块progress-upload__status,或用伪元素 + CSS 变量控制文本内容 - 把取消按钮写成
progress-upload__fill--cancel:取消是独立交互控件,应是progress-upload__action或progress-upload__cancel,修饰符不承载操作语义
用 --indeterminate 和 --error 代替 data-status
不要依赖 data-status="uploading" 或 data-percent="65" 驱动样式。CSS 层应通过修饰符响应状态:progress-upload--indeterminate(不确定进度,显示动画波纹),progress-upload--error(上传失败,背景变红+图标),progress-upload--success(完成,绿色+勾选图标)。
为什么不用 data-*:
-
data-percent会导致样式层与 JS 数值强耦合,比如后端返回 0.65 而不是 65,类名就得跟着改逻辑 - CSS 自定义属性(
--progress: 65)更灵活:progress-upload__fill { width: calc(var(--progress) * 1%); },JS 只需更新一个属性,无需操作类名 - 修饰符可组合:
progress-upload--indeterminate--dark合法,而data-status="indeterminate" data-theme="dark"在 HTML 中无法直观表达层级关系
progress-upload__label 不是装饰性文字,而是语义化元素
progress-upload__label 应该是显示文件名、大小、剩余时间等辅助信息的容器,不是可有可无的装饰。它必须与 __track 平级,同属 progress-upload 直接子元素。
典型结构:
<div class="progress-upload">
<div class="progress-upload__label">report.pdf (2.4 MB)</div>
<div class="progress-upload__track">
<div class="progress-upload__fill"></div>
</div>
</div>注意点:
- 不叫
progress-upload__text或progress-upload__desc:名词优先,label明确其作用是标注进度上下文 - 不嵌套在
__track内:否则语义坍塌,变成“轨道里的文字”,而它实际是平行信息模块 - 支持修饰符:
progress-upload__label--compact用于小尺寸场景(如列表项内),但不能用--hidden替代 JS 显隐控制——隐藏逻辑应在 JS 层管理类名增删
BEM 的边界感在这里特别关键:进度条不是“上传组件的一部分”,它是“上传流程中进度可视化这一职责的独立实现”。一旦开始往里塞取消按钮、重试链接、文件预览,就说明该拆新块了——比如 upload-summary 或 upload-action-group,而不是靠加深元素层级解决。


















