伪元素实现背景模糊但内容不模糊的原理是用::before创建独立图层并单独应用filter: blur(),内容因未继承滤镜而保持清晰;关键在于分层控制而非直接模糊容器。

伪元素实现背景模糊但内容不模糊的原理
核心是把伪元素 ::before 当成独立图层盖在内容下方,再对它单独应用 filter: blur();内容本身不继承模糊,自然保持清晰。关键不是“给背景加模糊”,而是“用伪元素伪造一个带模糊的底层”。
常见错误是直接对容器加 filter: blur(),结果整个盒子(含文字)一起糊掉——因为 filter 会作用于整个渲染树,无法只模糊背景。
::before 做模糊背景的必要 CSS 写法
必须满足三个条件:伪元素要铺满、要设 z-index 分层、要避免触发新层叠上下文导致遮挡失效。
- 伪元素需设
content: ""、position: absolute、inset: 0(或top/left/bottom/right: 0)确保铺满 - 父容器必须有
position: relative(或其它非static值),否则absolute会相对 viewport 定位 - 伪元素
z-index: -1是最稳妥做法;若设为0或更高,可能被后续兄弟元素盖住 - 别给父容器加
transform、will-change或opacity < 1,否则会创建新层叠上下文,让z-index: -1失效
简短示例:
立即学习“前端免费学习笔记(深入)”;
.blur-bg {
position: relative;
}
.blur-bg::before {
content: "";
position: absolute;
inset: 0;
z-index: -1;
background: url(./bg.jpg);
filter: blur(8px);
background-size: cover;
}
模糊背景和真实内容之间的视觉分离问题
即使伪元素模糊了,如果背景图太亮/太暗,或者内容没加足够对比度,文字仍会看不清——模糊只是“虚化”,不是“降噪”。
- 建议在伪元素上叠加一层半透明遮罩:
background: linear-gradient(rgba(0,0,0,0.3), rgba(0,0,0,0.3)), url(...) - 内容区域可加
backdrop-filter: blur(2px)(注意:这是另一层,仅作用于内容背后透出的部分,和伪元素无关) - 移动端 Safari 对
filter在::before上的支持较稳,但旧版 Android Webview 可能完全不支持,需检查caniuse filter
性能与重绘风险点
filter: blur() 是高开销操作,尤其在大尺寸容器或高频动画中,容易触发全层重绘甚至掉帧。
- 模糊半径别超过
12px,超过后性能下降明显,肉眼区分度却不大 - 避免在
:hover或@keyframes中动态改变blur()值——这会让浏览器反复生成高斯核,比静态模糊更卡 - 如果容器宽高会变(比如响应式伸缩),优先用
background-attachment: fixed配合小图平铺,而非拉伸大图再模糊
真正难处理的是滚动时的模糊背景:一旦伪元素随容器滚动,每次滚动都会触发滤镜重计算。这时候不如用固定定位 + background-attachment: fixed,或者干脆换 SVG 模糊滤镜预渲染。










