纯CSS实现progress波浪动画需用伪元素覆盖:隐藏原生填充条,设progress为relative定位,::after用repeating-linear-gradient双层错位渐变模拟波形,通过--pct变量动态控制宽度,并用JS同步更新value和--pct属性。

progress 标签本身不支持 CSS 动画填充,必须用伪元素模拟
原生 <progress> 的 ::webkit-progress-bar 和 ::webkit-progress-value 无法对 background 做 animation(WebKit 限制),直接写 background: linear-gradient(...); animation: wave; 无效。真实可行的方案是:隐藏原生填充条,用 ::after 伪元素盖在上面,再对伪元素做波浪动画。
- 必须设
progress::-webkit-progress-value { background: transparent; }清空默认背景 -
progress本身设position: relative,为伪元素提供定位上下文 - 伪元素宽度用
calc(var(--pct) * 1%)动态控制(需配合 JS 更新--pct自定义属性) - 波浪本质是
background-image: linear-gradient(...)+background-position-x循环位移
波浪纹核心 CSS:用 repeating-linear-gradient 模拟正弦曲线
不用 SVG 或 Canvas,纯 CSS 实现的关键是用两层错位的 repeating-linear-gradient 叠加出起伏感。单层渐变只能做条纹,双层水平偏移 + 不同角度才能“挤”出波形。
progress::after {
content: "";
position: absolute;
top: 0; left: 0; bottom: 0;
width: calc(var(--pct, 0) * 1%);
background:
repeating-linear-gradient(
-45deg,
#4f86ff,
#4f86ff 10px,
transparent 10px,
transparent 20px
),
repeating-linear-gradient(
45deg,
#4f86ff,
#4f86ff 10px,
transparent 10px,
transparent 20px
);
background-size: 20px 20px;
animation: wave 8s linear infinite;
}
@keyframes wave {
0% { background-position-x: 0, 0; }
100% { background-position-x: 20px, -20px; }
}注意第二层渐变角度必须与第一层相反(-45deg 和 45deg),且 background-position-x 两个值要反向变化,否则波形会平移而非起伏。
JS 动态更新进度时,必须同步修改 --pct 自定义属性
不能只改 value 属性——浏览器不会触发伪元素的宽度重算。必须显式设置 style.setProperty('--pct', newValue)。
立即学习“前端免费学习笔记(深入)”;
- 错误写法:
el.value = 65→ 伪元素宽度不变 - 正确写法:
el.value = 65; el.style.setProperty('--pct', 65); - 如果用
max不是 100,需换算:const pct = (el.value / el.max) * 100; - 动画流畅性依赖 requestAnimationFrame,避免高频直接赋值
IE 和 Firefox 兼容性处理:伪元素 fallback 方案
Firefox 完全不支持 progress::-moz-progress-bar 的伪元素覆盖,IE 更不支持。真要兼容,得放弃原生 <progress>,改用 <div role="progressbar"> 手动实现语义和键盘操作。
- aria-valuenow / aria-valuemin / aria-valuemax 必须同步更新
- 键盘支持:左右方向键增减进度,Home/End 跳转 0% / 100%
- 视觉上用
div套两层(外层 track,内层 fill + wave 伪元素),结构更可控 - Wave 动画在 Firefox 中表现正常,但 WebKit 内核(Safari/Chrome)需额外加
-webkit-mask防止溢出
波浪动效的节奏感很依赖 background-size 和 animation-duration 的匹配,调得太快像抖动,太慢像卡顿——建议从 6s–10s 区间试起,background-size 控制在 16px–24px 之间最自然。



















