box-shadow能实现外发光,但真内发光必须用伪元素;两者叠加时z-index、content和overflow是最易出错的三点。

直接说结论:box-shadow 能实现外发光边框,但真内发光必须用伪元素;两者叠在一起时,z-index、content 和 overflow 是最容易翻车的三个点。
box-shadow 外发光为什么总显得“硬”或“看不见”
外发光不是描边,是光晕扩散——纯 #fff 或 white 会因不透明导致边缘生硬;浏览器对原生 <progress>、<input type="range"> 等控件的 box-shadow 支持极差,常被忽略。
- 必须用
rgba()或hsla()控制透明度,例如box-shadow: 0 0 16px rgba(100, 150, 255, 0.6) - 模糊值(第三个参数)建议 ≥12px,太小看不出光晕,太大在移动端易掉帧
- 避免和
filter: drop-shadow()同时使用——渲染管线不同,叠加后模糊不可控 - Chrome DevTools 的 “Rendering” 面板打开 “Paint flashing”,能直观看到高模糊阴影是否频繁重绘
::before / ::after 模拟内发光的硬性前提
伪元素不是可选优化项,是实现“从内部透出光”的唯一可行路径。但漏掉任一条件,它就根本不渲染。
- 必须有
content: "",哪怕空字符串也不可省略 - 父容器需设
position: relative,伪元素用position: absolute - 伪元素宽高要覆盖完整区域:
top: -4px; right: -4px; bottom: -4px; left: -4px(数值按发光强度微调) - 层级必须明确:
z-index: -1让它沉在内容之下、背景之上;若背景是z-index: -2,这里就不能写 -1 - 遇到
overflow: hidden,伪元素会被裁掉——要么改父级为overflow: visible,要么用clip-path精确控制裁剪范围
内外发光同时存在时的常见视觉冲突
光晕打架、边缘重影、Safari 上闪烁,基本都源于叠加逻辑没理清。
立即学习“前端免费学习笔记(深入)”;
- 外发光走本体
box-shadow,内发光走伪元素box-shadow,两者不能混在同一个声明里 - 别给同一元素同时加
box-shadow和filter: drop-shadow(),尤其在动画中——Chrome 和 Safari 渲染行为不一致 - 多重
box-shadow叠加(如模拟多层光晕)建议 ≤3 层,超过人眼难分辨,且旧 Android WebView 可能轻微糊边 - 设计师给的 Figma 效果若含
Screen或Linear Dodge混合模式,CSS 无等效实现,只能用多层半透明rgba()近似妥协
真正麻烦的从来不是怎么写出来,而是当发光要适配圆角容器、滚动区域、悬停动画、甚至暗色模式时,每一处 border-radius、overflow、transform 都可能让光晕突然断裂或消失——这些细节不会报错,只会在某个特定设备上静默失效。


















