扫光效果本质是背景渐变位移,需用linear-gradient配合background-size和background-position动画实现,伪元素方案更稳妥,移动端需js监听坐标,blur需配translatez(0)和尺寸补偿。

扫光效果本质是背景渐变位移,不是加阴影
很多人一想到“光”就去调 box-shadow 或 text-shadow,结果做出来的是霓虹灯或投影,不是扫光。扫光的核心是模拟一束光从左到右(或对角)掠过按钮表面,靠的是 background-image + background-position 动画,配合 background-size 放大渐变区域,让位移产生“扫过”的错觉。
常见错误现象:光不动、只闪一下、边缘生硬、hover 时卡顿。根本原因往往是没设对 background-size,或动画没触发硬件加速。
-
background: linear-gradient(45deg, transparent, rgba(255,255,255,0.6), transparent)是基础——中间亮、两边透明,角度决定扫向(45deg 是对角,90deg 是垂直) -
background-size: 200% 200%必须设,否则background-position位移无效;值越大,扫速越慢、越平滑 - 必须加
transform: translateZ(0)或will-change: background-position,否则滚动或 hover 时掉帧 - 不要在
:hover里同时改background-position和box-shadow,浏览器会重绘整层
用伪元素实现按钮扫光,避免污染内容层
直接在按钮上设渐变背景会覆盖原有颜色或图片,更稳妥的做法是用 ::before 伪元素盖一层扫光层,主按钮保持原样式。这样结构清晰、便于复用,也方便控制层级和裁剪。
关键点在于容器要设 overflow: hidden,否则扫光层移出按钮区域会露馅;伪元素需绝对定位、全尺寸覆盖,并用 z-index 压在内容下方(但高于背景)。
- 按钮本身设
position: relative; overflow: hidden; -
::before设content: ""; position: absolute; top: 0; left: 0; width: 100%; height: 100%; - 伪元素的渐变背景用
linear-gradient(135deg, transparent, rgba(255,255,255,0.8), transparent),background-size: 300% 300% - 动画写在
::before:hover或独立@keyframes上,animation: shine 2.5s infinite,关键帧里只动background-position
移动端 touchmove 无法触发 hover,得监听坐标算偏移
纯 CSS 的 :hover 在 iOS 和安卓上基本失效(尤其 Safari),想让扫光“追着手指走”,必须用 JS 监听 touchmove 和 mousemove,动态算出鼠标/手指相对于按钮左上角的坐标,再转成 background-position 值。
最容易被忽略的是坐标系转换:用 e.clientX - rect.left,不是直接用 e.clientX;而且得限制偏移范围(比如 ±15px),否则快速划过时光斑飞出按钮外,失去“扫”的感觉。
- 先用
button.getBoundingClientRect()拿到按钮视口位置 - 监听
button.addEventListener('mousemove', handler)和button.addEventListener('touchmove', handler, { passive: false }) - 在 handler 里统一取坐标:
const x = e.touches ? e.touches[0].clientX : e.clientX - 计算相对偏移:
const dx = Math.max(-15, Math.min(15, x - rect.left)),再设button.style.backgroundPosition = `${dx}px ${dy}px`
多层扫光叠加容易糊,优先用单层高斯模糊替代
有人试图叠加多个 linear-gradient 或混用 filter: blur() 来增强光感,结果渲染变慢、边缘发虚、文字看不清。其实更高效的做法是:单层高质量渐变 + 伪元素 filter: blur(8px),再配低透明度(rgba(255,255,255,0.3))。
注意 filter: blur() 会扩大元素实际渲染尺寸,所以伪元素必须设 top: -4px; left: -4px; width: calc(100% + 8px); height: calc(100% + 8px); 补齐,否则光晕被裁掉。
- 别用两层以上渐变叠加做扫光,性能差且不可控
-
filter: blur()要搭配transform: translateZ(0)启用 GPU 加速,否则 iOS 上直接卡死 - 如果按钮有圆角,伪元素也要同步设
border-radius,否则光晕边缘是直角 - 深色背景上扫光明显,浅色背景建议提高渐变中白光的 alpha 值(如
rgba(255,255,255,0.7))
扫光效果看着轻巧,实际最常翻车的不是动画逻辑,而是坐标计算偏差、硬件加速漏加、以及模糊值和透明度没协同调优——这三个地方任一出问题,光就“飘”了或者“糊”了。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











