方形进度条应使用div+伪元素遮罩而非原生progress标签,推荐clip-path inset()实现,但需针对safari降级处理,避免直接操作style.clippath触发重排,用css变量配合transition优化性能。

方形进度条本质是 CSS 动画 + 伪元素遮罩,不是用 <progress></progress>
浏览器原生 <progress></progress> 只支持水平或垂直线性样式,强行拉成正方形会失真、无法控制角半径、动画卡顿。真正可靠的方案是用 div 搭配 ::before/::after 做视觉遮罩,靠 transform: scaleX() 或 clip-path 控制填充比例。
clip-path 实现最简洁,但要注意 Safari 15.4 以下不支持百分比 inset()
主流写法是用 clip-path: inset(0 <code>calc(100% - var(--p)) 0 0),其中 --p 是当前百分比(如 65)。但老 Safari 会把 calc(100% - 65%) 解析失败,直接显示满条。稳妥做法:
- 对 Safari 单独用 JS 动态设
clip-path: inset(0 <code>calc(35%) 0 0)(即硬算出未填充高度) - 或降级为
transform: scaleY()+origin-bottom,兼容性更好但需额外容器包裹 - 别用
clip-path: polygon()手动描点——维护成本高,小数点偏差就露白边
用 background-image 渐变模拟时,background-size 必须匹配容器宽高比
比如容器是 200px × 200px,想从左到右填充,得写:
background: linear-gradient(90deg, #4a90e2 0%, #4a90e2 65%, #e0e0e0 65%, #e0e0e0 100%); background-size: 200px 100%; background-repeat: no-repeat;
这里 background-size 的第一个值必须等于容器宽度,否则填充错位。如果容器响应式(如 width: 100%; aspect-ratio: 1),就得用 background-size: 100% 100% 配合 background-position 调整起始方向,否则在缩放时渐变会拉伸变形。
JS 更新进度时,避免直接操作 style.clipPath 触发强制同步布局
频繁调用 el.style.clipPath = 'inset(0 calc(100% - 72%) 0 0)' 会让浏览器反复计算几何属性,滚动中掉帧明显。更优解:
- 用 CSS 自定义属性驱动:先在 CSS 里写
clip-path: inset(0 calc(100% - var(--p, 0%)) 0 0),JS 只改el.style.setProperty('--p', '72%') - 动画交给
transition: clip-path 0.3s ease,而非 JS 定时器逐帧更新 - 若需精确到 0.1%,注意 Chrome 对
clip-path的 calc 精度限制,低于 0.5% 的变化可能被舍入
方形进度条的麻烦不在形状本身,而在「如何让填充动画在任意尺寸、任意缩放、任意浏览器下都保持像素级对齐」——这决定了你得在 CSS 层做足容错,而不是指望 JS 算准每个像素。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











