流光动画用::after而非直接改background是为了利用transform触发合成层,避免重绘;需设content:""和position:absolute,父元素设position:relative,仅用transform/opacity动画;linear-gradient需窄色标(如transparent,rgba(255,255,255,0.8),transparent 60%)模拟光刃;动画卡顿常因缺will-change、from/to写法或时长过短;深色背景发灰应改用background-blend-mode:screen或filter而非调opacity。
::after 而不是直接改 background
因为直接在按钮上用 background: linear-gradient 做动画会触发重绘(repaint),而把光效抽离到 ::after 伪元素后,配合 transform: translateX 移动,能走合成层(compositor layer),避免 Layout 和 Paint,性能更稳。
关键点:
::after 必须设 content: "",否则不渲染position: absolute,且父容器(按钮)要 position: relative
transform 和 opacity,别碰 left/width 等触发布局的属性linear-gradient 的角度和色标怎么配才像“流光”流光的本质是窄带高亮色快速扫过,不是渐变色铺满。所以要用极小的色标区间制造“光刃”效果:
background: linear-gradient( 90deg, transparent, rgba(255, 255, 255, 0.8), transparent 60%);
常见踩坑:
立即学习“前端免费学习笔记(深入)”;
100%(比如写 transparent 120%)会导致光带拉长、失真#fff 容易过曝,推荐 rgba(255, 255, 255, 0.6–0.8) 控制通透感90deg 是从左到右扫,-45deg 更接近真实打光方向,但需同步调整 transform 方向即使用了 transform,仍可能掉帧——大概率是以下原因:
will-change: transform(尤其 Safari 下明显)@keyframes 中用了 from/to 而非百分比,某些旧版 Chrome 解析不准1.2s),建议 ≥ 2s,配合 ease-in-out 更自然推荐写法:
@keyframes shine { 0% { transform: translateX(-100%) scaleX(0); } 100% { transform: translateX(100%) scaleX(0); }}
scaleX(0) 是为了隐藏光带两端毛边,比单纯透明更干净。
在深色主题下,直接降低 opacity 会让光效发脏。更优解是:
rgba(255, 255, 255, 0.8) 不变,改用 background-blend-mode: screen
::after 加 filter: brightness(1.3) contrast(1.2),比调 opacity 更可控mix-blend-mode,它会强制图层分离,在复杂堆叠场景下可能意外影响其他元素真正难调的从来不是动效本身,而是光效与不同背景色、不同文字颜色之间的视觉权重平衡——这个得靠眼力微调,没有万能参数。