box-shadow的inset模式本质是向内投射阴影,边缘亮中心暗,与内发光中心亮边缘晕开的视觉逻辑相反;需用::before叠加半透明白色层+大模糊box-shadow,并配合overflow:hidden裁剪实现真正内发光。

为什么直接用 box-shadow 做不出真正的内发光
因为 box-shadow 的 inset 模式本质是“向内投射阴影”,光是从外往里衰减的,边缘最亮、中心最暗——这和内发光(中心亮、边缘柔和晕开)视觉逻辑相反。强行调 inset 会得到一个灰扑扑的凹陷感,不是发光。
::before 叠加层的关键控制点
核心思路是:用 ::before 画一个和按钮等大的半透明白色(或主色)圆角矩形,再给它加一个大而虚的 box-shadow,最后用 overflow: hidden 把超出按钮区域的光晕裁掉,只留下“从内部渗出”的效果。
-
position: absolute且z-index设为负值(如-1),确保它在文字和边框之下 -
border-radius必须和按钮本身完全一致,否则光晕会在圆角处断裂 -
background-color推荐用rgba(255, 255, 255, 0.3)起手,太透明则不明显,太浓则像高光涂层 -
box-shadow用0 0 20px 8px rgba(255, 255, 255, 0.6)这类“无偏移 + 大模糊 + 正向扩张”组合,8px是关键扩张值,决定光晕厚度
必须加上的容器约束
光靠 ::before 不行,父元素(按钮本身)得配合裁剪:
- 按钮需设
position: relative,否则::before的绝对定位会脱标 - 必须设
overflow: hidden,否则光晕会溢出到按钮外,变成“外发光” - 如果按钮有
border,建议用background-clip: padding-box避免阴影被边框遮挡
示例最小结构:
.glow-btn {
position: relative;
overflow: hidden;
border-radius: 8px;
}
.glow-btn::before {
content: '';
position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
z-index: -1;
border-radius: 8px;
background-color: rgba(255, 255, 255, 0.25);
box-shadow: 0 0 24px 10px rgba(255, 255, 255, 0.7);
}
深色背景下的颜色适配陷阱
内发光不是固定用白色——在深色背景上用白光没问题,但若按钮底色是蓝色,又在浅灰背景上,白光会显得生硬。更稳妥的做法:
立即学习“前端免费学习笔记(深入)”;
- 把
background-color和box-shadow的颜色统一成按钮主色的浅色变体,比如rgba(59, 130, 246, 0.4) - 避免用
hsl()动态计算,CSS 不支持在::before里读取父元素颜色 - 如果要响应主题切换,得靠 JS 切换预设 class,纯 CSS 无法自动适配
真正难的不是实现,是让光晕在不同尺寸、不同圆角、不同背景色下都看起来“是从里面长出来的”,而不是贴上去的一层膜。这点没捷径,得调参数+截图对比。


















