扫光特效本质是CSS动画+伪元素遮罩,用::before创建渐变白条并水平移动实现方向感;必须包裹容器,设relative定位,动画时长1.2s–1.8s,移动端需改用点击态class适配。

扫光特效的本质是 CSS 动画 + 伪元素遮罩
不是靠 JS 控制图片亮暗,而是用 ::before 伪元素盖一层渐变白条,再用 animation 让它从左到右快速横移。浏览器渲染快、不卡顿,兼容性也够(Chrome/Firefox/Safari/Edge 均支持)。
常见错误是直接给 <img> 加 background 或试图用 filter: brightness() 模拟扫光——亮度变化是全局的,无法做出“一束光划过”的方向感和锐利边缘。
- 必须用
position: relative给图片容器设定位上下文 - 伪元素需设
content: "",否则不渲染 - 动画时长建议控制在
1.2s–1.8s,太快像闪屏,太慢失去“扫”感
HTML 结构要包裹容器,不能直接操作 img 标签
<img> 自身无法承载伪元素,所以必须套一层 <div class="glow-hover"> 或类似容器。这是最容易漏掉的一步,很多人写完 CSS 发现没反应,就是卡在这儿。
<div class="glow-hover"> <img src="photo.jpg" alt="示例图"> </div>
- 容器宽高需与图片一致(可设
display: inline-block避免空白间隙) - 不要给
<img>设width: 100%后又让容器不定宽——会导致扫光条错位 - 若图片响应式,容器要用
aspect-ratio或 JS 监听尺寸变化(简单场景推荐固定尺寸)
CSS 动画关键参数:transform + background-gradient
核心是用 linear-gradient 做窄白条,再靠 transform: translateX() 移动它。不用 left 是因为 transform 性能更好,尤其在 hover 频繁触发时。
立即学习“前端免费学习笔记(深入)”;
.glow-hover {
position: relative;
display: inline-block;
}
.glow-hover::before {
content: "";
position: absolute;
top: 0; left: -100%;
width: 100%; height: 100%;
background: linear-gradient(
90deg,
transparent,
rgba(255,255,255,0.8),
transparent
);
z-index: 1;
animation: glow-scan 1.4s ease-out forwards;
}
.glow-hover:hover::before {
animation-play-state: running;
}
@keyframes glow-scan {
to { transform: translateX(100%); }
}-
z-index: 1确保伪元素压在图片上,但别设太高(避免干扰其他层) -
ease-out让光尾减速,更接近真实扫光物理感 - 如果扫光太弱,调高
rgba(255,255,255,0.8)的 alpha 值;太刺眼就降到0.4–0.6
移动端适配与 hover 失效问题
iOS Safari 和部分安卓浏览器对 :hover 支持不稳定,点一下才触发、点两下才消失,甚至完全不响应。这不是代码错,是平台限制。
真正可用的解法只有两个:加点击态 class 或 放弃扫光改用 tap-highlight。前者需少量 JS:
document.querySelectorAll('.glow-hover').forEach(el => {
el.addEventListener('click', () => el.classList.toggle('glow-active'));
});然后把 .glow-hover:hover::before 换成 .glow-hover.glow-active::before。
- 别用
touchstart+touchend模拟 hover——手指滑动时会误触发 - 微信内置浏览器对
@keyframes有缓存 bug,加个空格或时间戳注释可绕过:/* v1.2 */ - 如果页面大量图片,动画同时跑太多可能掉帧,加
will-change: transform到伪元素上(仅必要时)
扫光看着简单,但光条角度、速度曲线、透明度衰减这些细节,调三次以上才容易出效果。别信“复制粘贴就能用”的说法。



















