真正能落地的只有两个路径:伪元素隔离模糊层(兼容性好但需手动构造图层)或用backdrop-filter模糊背后内容(语义清晰但旧浏览器静默失效);二者均需严格控制层叠顺序、定位上下文与背景继承。

直接用 filter: blur() 给整张图加模糊再局部“取消”,行不通——文字、按钮、图标全糊掉,这不是局部清晰,是全局废操作。真正能落地的只有两个路径:伪元素隔离模糊层,或用 backdrop-filter 模糊背后内容。
用 ::before 伪元素实现背景图局部模糊
核心是把模糊层和内容层彻底分开,避免 filter 波及文字或控件。
- 父容器必须显式设
position: relative,否则::before的position: absolute会往上找定位祖先,大概率错位 -
::before必须设z-index: -1,不是 0、不是 auto、不能省略——否则它压在内容上,你看到的永远是糊的 -
background: inherit只继承background-image和background-position,不继承background-size或background-color;务必手动补上background-size: cover和background-position: center - 如果父容器本身有
transform(比如scale(1.05)),可能触发新层叠上下文,此时内容也要加position: relative确保层级可控
用 backdrop-filter 实现真实“背后模糊”
它不处理当前元素,而是模糊它“背后透出来的内容”,所以语义对、效果干净,但限制极多。
- 必须配半透明背景:
background-color: rgba(255, 255, 255, 0.7);完全不透明 = 背后不可见 = 模糊失效 - 父容器不能有
overflow: hidden、transform或clip-path,否则背后内容被裁掉,backdrop-filter就没东西可模糊 - Safari 下必须写
-webkit-backdrop-filter,且要搭配border-radius或overflow: hidden才能防止模糊溢出圆角外(奇怪但真实) - 它不兼容 IE 和旧版 Android WebView,且在部分安卓浏览器中静默失效——没报错,也没效果
为什么不能直接给 img 加 filter: blur() 再局部还原
因为 img 是替换元素,它的内容不可被 CSS 层级穿透;你无法用另一个元素“盖住一部分再取消模糊”,也无法用 clip-path 切出清晰区后让滤镜只作用于剩余区域——filter 总是作用于整个渲染框。
立即学习“前端免费学习笔记(深入)”;
- 常见错误:用
div包img,然后对div加filter,再试图用子元素覆盖局部并设filter: none——无效,filter不继承也不可被子元素“中和” - 想做“左半边模糊、右半边清晰”?只能切图:两张图拼一起,或用 SVG mask +
filter,但维护成本陡增,响应式下极易崩 - 移动端尤其危险:
filter: blur(8px)在低端安卓机上容易掉帧,iOS Safari 对大于10px的值会降级为低精度模糊
模糊值与性能的实际取舍
别迷信“越大越高级”。blur 值直接影响合成层开销和重绘频率,尤其在滚动或动画中。
-
blur(4px)是多数场景的安全上限;blur(0)合法,blur(none)不合法且会清空整个filter链(比如同时有brightness()也丢了) - 需要动态调节模糊度(如滑块控制),别用
classList.toggle()切 class,要用 JS 拼完整style.filter字符串,并确保单位是px(blur(6px)✔,blur(6)✘) - 父容器设了
overflow: hidden却发现模糊“没生效”?大概率是溢出像素被硬裁了——加margin: 0 -6px或临时改成visible测试一下
最易被忽略的一点:所有方案都依赖图片已加载完成。如果 img 还在 loading 中,filter 或 backdrop-filter 作用的是空白画布,结果就是一片灰或黑,而不是模糊图。务必等 load 事件后再启用模糊逻辑,或用 IntersectionObserver 结合占位图预加载。



















