不能直接用<progress>因易被表格压缩变形且不支持双轨对比与动态归一化;须用<div>手动控宽,外层定宽高、内层行内设width%,并配合帆软列级聚合函数如ROUND(((G6-MIN(G6[!0;!0]))/(MAX(G6[!0;!0])-MIN(G6[!0;!0])))*100,0)+"%"实现归一化。

为什么不用 <progress> 直接塞进 <td>?
因为 <progress> 在表格单元格里容易被压缩变形,尤其当表格启用 table-layout: auto(默认)时,<progress> 的宽高会随内容或列宽被动拉扯,导致进度视觉失真。更关键的是:它不支持双轨对比(比如「完成值 vs 目标值」并排),也无法响应帆软、BI 工具中常见的列级动态归一化计算(如 (G6 - MIN(G6)) / (MAX(G6) - MIN(G6)))。这时候必须用 <div> 手动控宽。
<td> 里嵌 <div> 进度条的结构要点
核心是“容器定型、填充可控”——外层 <div> 必须脱离表格盒模型干扰:
- 外层
<div class="progress-cell">要设display: block、固定width(如120px)和height(如20px),不能用百分比或100% - 内层
<div class="progress-fill">只通过style="width: X%;"行内设置宽度,绝不能写死在 CSS 类里(否则无法绑定数据) - 每个进度条独占一个
<div>容器,不要把两个颜色块塞进同一个<div>做对比(padding/border 会导致总宽超 100%,视觉溢出) - 示例结构:
<td><div class="progress-cell"><div class="progress-fill" style="width: 75%;"></div></div></td>
帆软/BI 场景下动态计算百分比的 JS 表达式怎么写?
帆软里常见需求是:让当前单元格值按整列最大最小值归一化为 0–100%。错误写法是直接用 G6 * 100(没归一化),正确逻辑必须套用列聚合函数:
- 分母必须是
MAX(G6[!0;!0]) - MIN(G6[!0;!0]),其中[!0;!0]表示整列范围,避免被当前行过滤影响 - 分子是
G6 - MIN(G6[!0;!0]),确保最小值对应 0%,最大值对应 100% - 最终 width 值要四舍五入并加
%单位,例如:ROUND(((G6 - MIN(G6[!0;!0])) / (MAX(G6[!0;!0]) - MIN(G6[!0;!0])))*100,0) + "%" - 注意:如果分母为 0(全列值相同),需加判断避免除零错误,比如用
IF(MAX(G6[!0;!0]) = MIN(G6[!0;!0]), 100, ...)
CSS 样式里最容易忽略的三个细节
很多进度条看起来“卡顿”或“边缘模糊”,其实不是 JS 问题,而是 CSS 没压住:
立即学习“前端免费学习笔记(深入)”;
-
overflow: hidden必须加在外层容器(.progress-cell),否则width > 100%时会撑破表格 -
border-radius要同时加在外层和内层,否则圆角只出现在容器边缘,填充块直角突兀 -
transition: width 0.3s ease-in-out写在内层.progress-fill上,但前提是 JS 更新的是style.width,不是 class 切换——否则 transition 不触发
实际用的时候,最麻烦的不是写代码,而是确认数据源是否已做空值/异常值清洗;归一化公式一旦漏掉 [!0;!0] 范围标记,整列进度就会按当前行上下文计算,结果完全失真。



















