你是否曾遇到这样的情况:为一个造型别致的工具提示框或者含有伪元素的图标添加阴影时,最终呈现的却是一个方方正正的黑色矩形?按理说阴影应紧密贴合不规则轮廓,为何会变回规整的方形?
问题的根源在于drop-shadow的工作原理——它依据的是元素的Alpha通道(即透明度轮廓边缘),而非盒模型定义的矩形边界。因此,若直接将filter: drop-shadow()应用于伪元素或子元素,往往无法达到预期效果。决定成败的关键在于层级结构以及容器元素的控制。
务必应用于最外层父容器
一个常见的误区是:将drop-shadow直接施加给::before伪元素或图标元素自身,结果阴影依然是矩形。原因其实很简单——滤镜仅对当前渲染层产生作用。对于伪元素、SVG、PNG这类拥有透明边缘的元素,必须由同一层“蒙版”统一输出阴影,才能实现贴合轮廓的效果。
正确的做法是:
- 将
filter: drop-shadow(...)指定在包含主内容与伪元素的最外层父容器上,例如.tooltip或.bubble等包装元素。 - 该容器绝对不能设置
overflow: hidden,否则伪元素区域会被裁剪,导致Alpha轮廓被截断。 - 伪元素必须与主内容处于同一渲染层级,即两者都应作为该容器的直接子元素或伪元素,不可嵌套在子容器内部。
- 若使用
标签加载PNG图片,需确保其不被父容器的背景所遮盖。更可控的方案是改用background-image或。
参数语法与常见陷阱
接下来看参数。drop-shadow()的语法虽然与box-shadow相似,但缺少了两个关键功能:不支持spread-radius,也不支持inset。一旦参数写错,浏览器会静默忽略。
- 正确写法示例:
filter: drop-shadow(2px 2px 4px rgba(0,0,0,0.12))。该函数仅接受四个参数:水平偏移、垂直偏移、模糊半径及颜色。 - 错误写法示例:
filter: drop-shadow(2px 2px 4px 2px #000)。其中第四个数值(spread)将被直接丢弃,不会报错但也不会生效。 - 若想模拟“底部加强阴影”,不建议通过调整负值
offset-y配合较大blur-radius的方式,因为这容易导致阴影模糊成一团。更精确的做法是使用伪元素叠加一层box-shadow。 - 制作发光效果时,建议使用纯色代替
rgba(),例如drop-shadow(0 0 12px #00aaff)。多层发光效果可通过逗号分隔多个drop-shadow函数实现,如drop-shadow(0 0 8px #ff00aa) drop-shadow(0 0 16px #00aaff)。
性能与兼容性注意事项
还需关注性能问题。在滚动或hover动画等需要频繁重绘的区域,使用drop-shadow需谨慎,因为它会触发完整的图像滤镜计算,性能开销明显高于box-shadow。
- 静态卡片、弹窗、图标等无交互元素:可放心使用。
- 列表项hover、轮播图切换、拖拽实时阴影等场景:建议优先使用
box-shadow配合border-radius进行模拟,或通过伪元素绘制简化版的阴影。 - 兼容性方面:旧版Safari可能需要添加
-webkit-filter前缀,不过iOS 13及以上版本已基本无需此项处理。 - 透明PNG的陷阱:若阴影不可见,请先检查图片导出时是否保留了完整的Alpha通道。某些工具(例如Sketch在导出时勾选了“忽略透明度”)会直接丢弃透明信息。
总结而言,最容易被忽视的核心要点是:drop-shadow并非“为某个形状添加阴影”,而是“对当前渲染层的Alpha蒙版进行整体投影”。因此,容器结构、溢出控制以及伪元素层级等要素,往往比参数本身更能决定最终效果的成败。
