css backdrop-filter不适用于Chrome中的嵌套元素

sz81bmfz  于 2023-05-19  发布在  其他
关注(0)|答案(2)|浏览(217)

我有一个div.outer和一个div.inner,都有position: absolute;backdrop-filter: blur(8px);
https://jsbin.com/nihakiqocu/1/edit?html,css,output
Safari(左)给出了想要的结果--两个div都模糊了它们后面的内容。
然而,Chrome(右)只应用div.outer的模糊:

我有一个解决办法:在div.outer中添加另一个div,并将backdrop-filter: blur(8px);移动到该新div。
但是,我希望有一种解决方案,不需要从第一个jsbin开始更改DOM。还有,有谁知道是什么原因导致的--是Chrome的bug吗?
https://jsbin.com/rasudijame/1/edit?html,css,output
PS:它可以在iOS的Chrome上运行,但不能在Android的Chrome上运行,也不能在Mac OS的Chrome上运行

m3eecexj

m3eecexj1#

将背景滤镜放在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;
}
<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>

这里是codepen

kh212irz

kh212irz2#

这个答案完成了来自@ Michau的答案(对我来说很有效)。简短回答:Chrome会自动阻止嵌套的背景过滤器堆叠。

为什么Chrome会这样

一个very similar issue已经在 chrome bug跟踪器上报告。引用此bug报告的答案:
backdrop-filter将过滤它后面的所有内容,直到“Backdrop Root”,它由几个触发器组成。其中一个触发器是另一个backdrop-filter元素。
所以基本上,当你将backdrop-filter添加到一个元素中时,它将成为新的background根:嵌套的背景过滤器将不会应用于它的任何祖先,因为它们不能“看到”根之上。

<elem1>
  <!-- Here, backdrop filter will apply to elem1, -->
  <!-- as it is an ancestor of elem2 -->
  <elem2 style="backdrop-filter: ...">
    <!-- Here, backdrop filter will apply to elem2, -->
    <!-- but not elem1, as elem2 is now the new Backdrop root -->
    <elem3 style="backdrop-filter: ...">
    </elem3>
  </elem2>
</elem1>

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

为什么接受的答案有效

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

为什么在其他浏览器上也能用

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

摘要

如果你想让一个带有背景滤镜的元素允许嵌套的背景(例如,一个透明的导航栏和一个下拉菜单都有模糊/透明的效果),你应该把滤镜应用到一个伪元素上,就像@ Michal建议的那样:

/* replace */
.parent {
  backdrop-filter: /*...*/;
}

/* with */
.parent::before {
    content: '';
    position: absolute;
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
    backdrop-filter: /*...*/;
    z-index: -1;
}

注意:你只需要在父容器有嵌套元素的时候设置背景过滤器,而不是在“叶子”元素上。

相关问题