背景过滤器不适用于 Chrome 中的嵌套元素

Ton*_*ump 10 html css css-filters

我有一个div.outerand 里面 a div.inner,都带有position: absolute;backdrop-filter: blur(8px);

https://jsbin.com/nihakiqocu/1/edit?html,css,output

Safari(左)给出了想要的结果——两个 div 都模糊了它们背后的东西。

但是,Chrome(右)仅应用以下模糊div.outer

苹果浏览器铬合金

我有一个解决方案:在里面添加另一个 divdiv.outer并移动backdrop-filter: blur(8px);到那个新的 div。

但是,我希望有一个不需要从第一个 jsbin 更改 DOM 的解决方案。另外,有没有人知道是什么原因造成的——这是一个 Chrome 错误吗?

https://jsbin.com/rasudijame/1/edit?html,css,output

PS:它适用于 iOS 的 Chrome,但不适用于 Android 的 Chrome,也不适用于 Mac OS 的 Chrome

Kaw*_*aLo 9

这个答案完成了@Micha\xc5\x82 的答案(对我有用)。简短回答:Chrome 会自动阻止嵌套背景滤镜堆叠。

\n

为什么 Chrome 会这样

\n

chromium bug tracker 上也报告了一个非常类似的问题。引用这个错误报告的答案:

\n
\n

背景过滤器将过滤其后面的所有内容,直到由多个触发器形成的“背景根”。其中一个触发器是另一个背景过滤器元素。

\n
\n

所以基本上,当您添加backdrop-filter到一个元素时,它会成为新的背景根:嵌套的背景过滤器不会应用于它的任何祖先,因为它们无法“看到”根之上。

\n
<elem1>\n  <!-- Here, backdrop filter will apply to elem1, -->\n  <!-- as it is an ancestor of elem2 -->\n  <elem2 style="backdrop-filter: ...">\n    <!-- Here, backdrop filter will apply to elem2, -->\n    <!-- but not elem1, as elem2 is now the new Backdrop root -->\n    <elem3 style="backdrop-filter: ...">\n    </elem3>\n  </elem2>\n</elem1>\n
Run Code Online (Sandbox Code Playgroud)\n

Chrome 实际上遵循 W3C 的建议(或者看起来是这样)。如果您有动力,您可以阅读此 W3C 草案中存在此行为的完整原因。

\n

为什么接受的答案有效

\n

:before一个伪元素,这意味着它没有子元素。因此,即使它成为背景根,它也不会阻止嵌套过滤器应用于其祖先。

\n

为什么它可以在其他浏览器上运行

\n

截至 2023 年 5 月,我能够在 Chrome、Safari 和 Firefox 上测试此行为。似乎只有 Chrome 遵循此 W3C 草案,因为 Safari 和 Firefox 上的元素已正确模糊。然而,根据错误报告的答案,Safari 和 Firefox 偏离了规范。

\n

概括

\n

如果您希望带有背景过滤器的元素允许嵌套背景(例如,带有下拉菜单的透明导航栏,两者都具有模糊/透明效果),则应该将过滤器应用于伪元素,如 @Micha\ xc5\x82 建议:

\n
/* replace */\n.parent {\n  backdrop-filter: /*...*/;\n}\n\n/* with */\n.parent::before {\n    content: \'\';\n    position: absolute;\n    width: 100%;\n    height: 100%;\n    top: 0;\n    left: 0;\n    backdrop-filter: /*...*/;\n    z-index: -1;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

注意:仅当父容器具有设置了背景过滤器的嵌套元素(而不是“叶子”元素)时,才需要执行此操作。

\n


小智 7

将背景过滤器放在 css 伪元素上。这允许嵌套背景过滤器。您也可以使用z-index: -1;将背景放置在元素后面

div {
  height: 100px;
  width: 100px;
}
.wrapper {
  position: absolute;
}
.outer, .inner {
  position: relative;
}
.outer::before {
  content: '';
  position: absolute;
  width: 100%;
  height: 100%;
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
}
.outer {
  background: rgba(255, 0, 0, .5);
}
.inner::before {
  content: '';
  position: absolute;
  width: 100%;
  height: 100%;
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  
}
.inner {
  background: rgba(0, 0, 255, .5);
  top: 50px;
  left: 50px;
}
main {
  position: relative;
}
Run Code Online (Sandbox Code Playgroud)
<main>
  <div class="wrapper">
    <div class="outer">
      <div class="inner"></div>
    </div>
  </div>

  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusamus in id quos, est voluptatibus minus porro sunt totam quod commodi odit maxime similique, dolorum aut quo atque. Deleniti, voluptas animi.</p>
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusamus in id quos, est voluptatibus minus porro sunt totam quod commodi odit maxime similique, dolorum aut quo atque. Deleniti, voluptas animi.</p>
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusamus in id quos, est voluptatibus minus porro sunt totam quod commodi odit maxime similique, dolorum aut quo atque. Deleniti, voluptas animi.</p>
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusamus in id quos, est voluptatibus minus porro sunt totam quod commodi odit maxime similique, dolorum aut quo atque. Deleniti, voluptas animi.</p>
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusamus in id quos, est voluptatibus minus porro sunt totam quod commodi odit maxime similique, dolorum aut quo atque. Deleniti, voluptas animi.</p>
</main>
Run Code Online (Sandbox Code Playgroud)

这是codepen

  • 如果这对任何人都不起作用,我发现对我来说的解决方案是减少(或删除)堆栈中较低元素的 z 索引。不知道为什么,但玻璃层 (z 1000) 不适用于早期的同级 (z 100),但将同级减少到 z 10 修复了它。 (4认同)
  • 我遇到了这个问题,花了很长时间才解决。就我而言,有两个罪魁祸首:“不透明度”和“投影”。设置不透明度会破坏模糊效果,因此您应该(就像在这个答案中一样)使用 `rgba(r, g, b, *此处不透明度*)`。第二个是“投影”。如果我想要模糊的元素也有“drop-shadow”,它会添加阴影,但模糊会消失。我希望这有帮助。 (4认同)
  • @Sibidharan自从我解决这个问题以来已经很长时间了,但我可以这样说:我现在使用两个固定标题,一个用于过滤效果,一个用于内容。这似乎对我有用。类似于:`&lt;header&gt;&lt;div class="glass"/&gt;&lt;nav /&gt;&lt;/header&gt;`。使标题位置:固定,使子位置:绝对,这样一切工作应该没有问题。 (3认同)
  • @MikeStopContinues 我修好了它..一切都很好:)你的回答对人有帮助。谢谢。 (2认同)