因为<progress>是替换元素,不支持::before/::after伪元素;需用div模拟结构,在.progress-fill::after上实现发光动画,依赖linear-gradient、background-size和background-position配合。

为什么直接给 progress 元素加 ::after 没反应
因为原生 <progress> 是替换元素(replaced element),不支持伪元素 ::before 和 ::after。浏览器会直接忽略对它的伪元素声明——这不是写法错,是规范限制。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 用
<div>模拟进度条结构,例如外层progress-bar容器 + 内层progress-fill - 把发光动画放在
.progress-fill::after上,确保父容器position: relative,且.progress-fill有position: relative或absolute - 避免用
display: inline或display: contents的父级,否则::after定位失效
::after 发光动画依赖线性渐变和位移的关键参数
发光感本质是高亮色块沿进度方向快速扫过,不是单纯改变透明度。核心是 background: linear-gradient 配合 background-position 动画。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 渐变方向必须与进度方向一致:水平进度用
to right,垂直进度用to bottom - 渐变色带要窄(如
0%, 10%, 20%, 100%),中间留白区域形成“光斑”视觉;全段同色无法产生扫光效果 - 动画用
background-position: 0% 50%, 100% 50%循环,不能只写一个值,否则无位移 - 务必设
background-size: 200% 100%(水平进度)或100% 200%(垂直),否则background-position无效
示例关键片段:
.progress-fill::after {
content: '';
position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.8), transparent);
background-size: 200% 100%;
animation: shine 2s infinite;
}
@keyframes shine {
0% { background-position: -100% 50%; }
100% { background-position: 100% 50%; }
}发光进度条在 Safari 上闪烁或不动的兼容处理
Safari 对 background-position 动画的硬件加速支持较弱,尤其在 ::after 上容易卡顿或跳帧。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 强制开启 GPU 加速:给
::after加transform: translateZ(0)或will-change: background-position - 避免同时动画多个属性(比如别再加
opacity),Safari 会降级为软件渲染 - 如果仍闪烁,改用
mask-image+animation替代:用渐变遮罩移动,底层统一高亮色,更稳定 - 注意 iOS Safari 15.4+ 才完整支持
background-position在伪元素上的动画,旧版本需降级为纯边框光晕
如何让发光效果随进度实时响应而非固定循环
固定动画(如上面的 shine)只是装饰,真正要“随进度发光”,得把光斑位置绑定到当前填充宽度。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 纯 CSS 无法读取
width百分比并动态计算background-position,必须用 JS 控制style.setProperty('--pos', `${percent}%`) - 定义 CSS 变量:
.progress-fill::after { background-position: var(--pos) 50%; } - JS 中每次更新进度时同步设置变量,例如
el.style.setProperty('--pos', (percent * 2 - 100) + '%')(根据background-size调整系数) - 别用
transition过渡background-position,它和动画冲突;优先用requestAnimationFrame驱动 JS 更新
复杂点在于:光斑要“从左进、居中亮、右出”,起始/结束位置必须和当前 width 匹配,否则在低进度(如 10%)时看到光斑一半在填充区外——这恰恰是最容易被忽略的细节。


















