如何仅对背景图片应用CSS filter滤镜而不影响子元素?
问题描述
我制作了一个全屏滚动(scroll-snap)的HTML页面,页面包含多个上下排布的主题板块,可通过向下滚动查看。不同板块通过background-image: url("image.png")标签设置了不同的背景图片。
我的代码如下:
<!DOCTYPE html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous"> <style> body, html { height: 100%; } body { background-color: black; } .slides { height: 100%; overflow: scroll; overflow-x: hidden; scroll-snap-type: y mandatory; } .slide { height: 100%; background-attachment: fixed; background-position: center; background-repeat: no-repeat; background-size: cover; scroll-snap-align: start; } .home { background-image: url("/img/bg.jpg"); } .band { background-image: url("/img/bg2.jpg"); } .pictures { background-image: url("/img/bg3.jpg"); } </style> </head> <body> <div class="slides"> <div class="slide home"></div> <div class="slide band"></div> <div class="slide pictures"></div> </div> </body> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL" crossorigin="anonymous"></script> </html>
当我尝试使用以下代码应用滤镜时:
filter: brightness(60%) blur(4px); -webkit-filter: brightness(60%) blur(4px);
滤镜会模糊div内的所有子元素,而非仅背景图片。我曾尝试使用backdrop-filter但未成功,现寻求可行的解决方法。
解决方案
方法一:利用伪元素承载背景与滤镜
把背景图移到.slide的::before伪元素上,给伪元素设置滤镜,同时通过定位让伪元素成为底层背景,不影响上层内容。
修改后的CSS代码:
body, html { height: 100%; } body { background-color: black; } .slides { height: 100%; overflow: scroll; overflow-x: hidden; scroll-snap-type: y mandatory; } .slide { height: 100%; scroll-snap-align: start; /* 让伪元素相对于当前slide定位 */ position: relative; overflow: hidden; } .slide::before { content: ""; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background-attachment: fixed; background-position: center; background-repeat: no-repeat; background-size: cover; /* 应用目标滤镜 */ filter: brightness(60%) blur(4px); -webkit-filter: brightness(60%) blur(4px); /* 将伪元素置于底层 */ z-index: -1; } .home::before { background-image: url("/img/bg.jpg"); } .band::before { background-image: url("/img/bg2.jpg"); } .pictures::before { background-image: url("/img/bg3.jpg"); }
方法二:嵌套div分离背景与内容
给每个.slide内部添加独立的背景div和内容div,滤镜仅作用于背景div,内容div通过定位叠在上方。
修改后的HTML结构:
<div class="slides"> <div class="slide"> <div class="slide-bg home"></div> <!-- 这里添加板块内容 --> <div class="slide-content">首页内容</div> </div> <div class="slide"> <div class="slide-bg band"></div> <div class="slide-content">乐队介绍</div> </div> <div class="slide"> <div class="slide-bg pictures"></div> <div class="slide-content">图片集</div> </div> </div>
对应的CSS代码:
body, html { height: 100%; } body { background-color: black; } .slides { height: 100%; overflow: scroll; overflow-x: hidden; scroll-snap-type: y mandatory; } .slide { height: 100%; scroll-snap-align: start; position: relative; overflow: hidden; } .slide-bg { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background-attachment: fixed; background-position: center; background-repeat: no-repeat; background-size: cover; filter: brightness(60%) blur(4px); -webkit-filter: brightness(60%) blur(4px); z-index: -1; } .home { background-image: url("/img/bg.jpg"); } .band { background-image: url("/img/bg2.jpg"); } .pictures { background-image: url("/img/bg3.jpg"); } .slide-content { position: relative; z-index: 1; /* 可自定义内容样式,比如文字颜色、内边距 */ color: #fff; padding: 2rem; }
关于backdrop-filter无效的说明
backdrop-filter是对元素后方的内容应用滤镜,而非元素自身的背景图。如果你的.slide没有透明背景,或者后方没有其他可见内容,这个属性自然不会产生效果,因此它不适合处理自身背景图的滤镜需求。
内容的提问来源于stack exchange,提问作者Nickessss
相关产品推荐
相关产品推荐

