暗角效果必须用伪元素实现,高光优先用drop-shadow();关键需设父容器position: relative、::before用inset:0和径向渐变;响应式与暗色模式下须用相对单位和css变量动态校准。

暗角效果必须用伪元素,不能直接 filter
直接对 img 元素加 filter: drop-shadow() 或 blur() 做暗角,结果只会是整张图发灰或模糊,不是你想要的「中心亮、边缘渐暗」。真正可控的暗角,得靠 ::before 伪元素盖一层径向渐变。
关键点有三个:
- 图片父容器必须设
position: relative,否则::before会相对于body定位,一动就跑偏 -
::before要写inset: 0(比top/left/width/height更稳),且加content: ""和pointer-events: none - 渐变写成
radial-gradient(circle at center, rgba(0,0,0,0) 70%, rgba(0,0,0,0.15) 100%):70% 是安全阈值,低于它暗角收缩成黑点,高于它过渡生硬;0.15是透明度上限,超了就像蒙了层灰布
高光效果优先用 drop-shadow(),别碰 background-position 动画
给图片加「轮廓发光」,filter: drop-shadow(0 0 12px rgba(255, 215, 0, 0.7)) 是最干净的解法——它严格贴合 PNG 透明边缘,不依赖额外 DOM,也不怕缩放错位。
容易踩的坑:
- 忘了设
transition: filter 0.3s ease,hover 时发光开关像灯泡一样“啪”一下,毫无质感 - 父容器写了
overflow: hidden,发光部分被裁掉,查半天发现是容器在背锅 - 在 Safari 旧版里没加
-webkit-filter前缀,效果直接消失(虽然现在基本不用了) - 想增强层次?叠两层就行:
drop-shadow(0 0 8px #ffcc00) drop-shadow(0 0 16px rgba(255, 100, 0, 0.4)),外层更虚、更淡,符合光学逻辑
响应式下暗角和高光都得防“缩放失步”
图片用 object-fit: cover 或容器宽高比不固定时,伪元素暗角容易盖住不该盖的区域,或者漏白边;而 drop-shadow 虽然轮廓跟随,但模糊半径在 DPR > 1 的屏上可能显得过厚。
解决办法很实在:
- 暗角伪元素的渐变半径改用
150%或200%(不是像素值),让它随图片缩放自适应 - 高光如果在高清屏上太刺眼,把模糊值从
12px改成1.2rem或clamp(8px, 1.2vw, 16px),用相对单位缓冲设备差异 - 别在
<picture></picture>或<source></source>上直接写filter,要作用于内部的<img>实例,否则 srcset 切图后滤镜不生效
暗色模式下,暗角和高光要重新校准
深色背景(比如 #121212)下,原暗角的 rgba(0,0,0,0.15) 会显得更重,高光的 rgba(255,215,0,0.7) 可能过曝。这时候不能复用同一套值。
稳妥做法是用 CSS 自定义属性分层控制:
- 定义
--dark-corner-alpha: 0.08和--dark-glow-strength: 0.4 - 在
@media (prefers-color-scheme: dark)里覆盖这两个值 - 暗角渐变写成
radial-gradient(circle at center, rgba(0,0,0,0) 70%, rgba(0,0,0,var(--dark-corner-alpha)) 100%) - 高光写成
drop-shadow(0 0 12px hsl(45 100% 70% / var(--dark-glow-strength))),用 HSLa 更易控色相与通透感
最常被忽略的一点:暗色模式切换时,如果图片父容器有 transform: translateZ(0) 或 will-change: transform,Chrome 115+ 可能丢掉 filter 合成层——得手动加 will-change: filter 触发更新,但仅限高频切换场景,否则耗电。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











