box-shadow无法实现渐变阴影和倒影,必须用::before和::after伪元素分层处理:::before做渐变模糊阴影,::after翻转图片并mask渐隐倒影,通过z-index分层控制叠加顺序。

box-shadow 不能给图片加渐变阴影,更不能直接生成倒影——它只接受颜色值,linear-gradient() 是图像类型,两者不兼容。真要同时实现“渐变阴影 + 倒影”,得用伪元素分两层处理:一层翻转图片做倒影,一层叠在下方模拟渐变阴影。
为什么不能只用 ::after 一个伪元素搞定
倒影需要原图翻转 + 透明度衰减,渐变阴影需要模糊 + 渐变背景 + 精确偏移,两者叠加区域、transform 和 filter 的作用顺序会互相干扰。强行塞进同一个伪元素,容易出现:翻转后模糊失效、渐变方向错乱、边缘糊成一片、或倒影被阴影完全盖住。
- 翻转(
scaleY(-1))必须作用于图像本身,而模糊(filter: blur())对已翻转的图像再处理,效果不可控 -
mask-image或opacity控制倒影渐隐,和阴影的linear-gradient(transparent, rgba())在同一层时无法独立调节衰减曲线 - 真实倒影底部应比顶部更虚、更淡;而阴影需要底部最浓、向上渐淡——二者衰减方向相反
::before 做渐变阴影,::after 做倒影:分工明确
把两个效果拆开,各自用一个伪元素,通过 z-index 分层控制渲染顺序。主图在中间层,::before(阴影)在最底层,::after(倒影)在中间偏下,这样倒影能压住阴影上半部分,形成自然过渡。
-
::before:绝对定位到底部外侧,width: 100%,height: 24px,background: linear-gradient(to bottom, transparent, rgba(0,0,0,0.25), transparent),加filter: blur(6px),z-index: -2 -
::after:定位在主图正下方(top: 100%),height: 80%,background: url(...)复制原图,transform: scaleY(-1),transform-origin: top,再用mask-image: linear-gradient(to bottom, #0008, transparent)实现上浓下淡的倒影衰减 - 父容器必须设
position: relative,且主img不能设display: block以外的布局干扰(比如vertical-align会影响伪元素定位基准)
常见错误:倒影边缘发虚或断层
不是代码写错了,是 transform: scaleY(-1) 和 mask-image 的像素对齐没处理好。尤其当图片宽高不是整数像素、或父容器有 subpixel 缩放时,翻转后边缘会出现半像素模糊或白边。
立即学习“前端免费学习笔记(深入)”;
- 确保原图 URL 在
::after和img中完全一致(包括路径大小写、查询参数),否则浏览器可能加载两份解码资源,尺寸微差导致错位 - 加
image-rendering: -webkit-optimize-contrast或image-rendering: crisp-edges强制像素对齐(对小图有效) - 避免用
border-radius直接切主图圆角——倒影也会被切,看起来像缺了一块;应改用overflow: hidden包裹容器,再对容器设圆角 - 如果倒影底部突然消失,检查
mask-image的渐变终点是否用了transparent而非rgba(0,0,0,0)(后者在某些 Safari 版本中不触发遮罩)
真正难的不是写出来,而是让倒影和阴影在不同缩放、不同 DPR 屏幕下都保持像素级干净——这要求你必须测试 devicePixelRatio === 2 和 scale(0.75) 场景下的伪元素尺寸与 blur() 值匹配。别省掉这一步。


















