从子元素中移除混合模式

17
我该如何在一个元素上设置mix-blend-mode,但不影响它的子元素?将子元素设置为默认值normal似乎无效:

http://jsfiddle.net/uoq916Ln/1/


这与不透明度的问题相同。实际上并不是属性被继承了,而是整个块都使用了这种效果进行渲染。 - vals
5个回答

15

如何避免mix-blend-mode影响子元素的解决方案:

  1. 让子元素定位为相对位置,并给它指定宽度和高度;
  2. 在子元素内部创建一个真实或伪元素,将其绝对定位并应用mix-blend-mode
  3. 在子元素内创建一个inner元素来放置内容,并将其定位为绝对位置并置于其他元素之上;

实时示例

HTML

<div class="bkdg">
    <div class="blend">
        <div class="inner">
            <h1>Header</h1>
        </div>
    </div>
</div>

层叠样式表 (CSS)

.blend {
    position: relative; /* Make position relative */
    width: 100%;
    height: 100%;
}

.blend::before { /* Apply blend mode to this pseudo element */
    content: '';
    width: 100%;
    height: 100%;
    position: absolute;
    left: 0;
    top: 0;
    z-index: 1;
    background-color: green;
    mix-blend-mode: multiply;
}

.inner { /* This is our content, must have absolute position */
    position: absolute;
    z-index: 2;
}

h1 {
    color: white;
}

6

我知道这个问题是两年前提出的,但它可能在未来很有用,因为它可能是比创建伪元素更好的解决方案。

有CSS isolation 属性,允许选择子元素是否应该在其父元素的上下文中呈现(auto)或作为新上下文的一部分呈现,因此不会对其应用任何混合模式(isolate)。

请查看this page以获取示例


2
如果我没错的话,隔离(isolation)只能保护元素的同级兄弟不受混合模式(mix-blend-mode)的影响。它对子元素无效。 - Driesketeer

4

有人评论说整个区块都被渲染了,这就是你遇到问题的原因。我通过从该区块中移除h1元素、设置绝对定位和z-index为1来实现你想要做的事情。这里有一个jsfiddle展示效果。

html

<div class="bkdg">
    <h1>Header</h1>
    <div class="blend">
    </div>
</div>

css

.blend {
    background-color: green;
    mix-blend-mode: multiply;
    width: 700px;
    height: 35px;
}
h1 {
    color: white;
    position: absolute;
    top: -15px; left: 10px;
    z-index: 1;
}

https://jsfiddle.net/jckot1pu/


2
这是一个棘手的问题。虽然它可以实现你想要的效果,但你可能不认为这是一个解决方案,我可以理解这一点。然而,在我的经验中,我发现有时为了实现你想要的CSS样式,你必须采取迂回的方式。 - Jpsh

3

无法从其子元素中删除元素的mix-blend-mode。

MDN表示,mix-blend-mode

设置一个元素的内容如何与其父元素和元素的背景混合

为了实现所需效果,将子元素放置在单独的层叠上下文中,并确保它位于设置了mix-blend-mode的元素之上。

要使其工作,需要两件事情:

  • 确保你的不透明内容(文本)不是设置背景和混合模式的元素的子元素。例如,使用CSS Grid Layout
  • 确保文本被渲染在设置背景和混合模式的元素之上,从而不受其影响。 在背景上设置mix-blend-mode会为其创建一个层叠上下文,您可能需要为您的内容提供自己的层叠上下文以确保它被呈现在其上面。

使用CSS Grid定位元素:

  • 定义一个具有一个自动大小的网格区域的网格容器
  • 将背景元素和文本元素都放置在该网格区域内(使它们重叠)
  • 让文本元素决定网格区域的大小
  • 使背景元素延伸到由文本元素大小决定的网格区域的大小

然后,在文本元素上设置isolation: isolate以确保它被渲染在背景元素上方,而不是在其下方。

一个工作示例:

.container {
  display: grid;
  grid-template-areas: 'item';
  place-content: end stretch;
  height: 200px;
  width: 400px;
  background-image: url(https://picsum.photos/id/237/400/200);
  background-size: cover;
  background-repeat: no-repeat;
}

.container::before {
  content: '';
  grid-area: item;
  background-color: seagreen;
  mix-blend-mode: multiply;
}

.item {
  grid-area: item;
  isolation: isolate;
  color: white;
}

h1,
p {
  margin: 0;
  padding: 10px;
}
<div class="container">
  <div class="item">
    <h1>HEADLINE</h1>
    <p>Subhead</p>
  </div>
</div>


0
如果您正在使用由Rashad Ibrahimov发布的优秀伪元素::before/::after解决方案,请注意以下重要事项。
我发现,只有在将z-index从父元素中移除并仅将其应用于伪元素和子元素之前,mix-blend-mode: multiply才能正常工作。
例如:
#wrapper {
    position: relative;
}

#wrapper .hoverlabel {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    /* z-index: 90; Uncomment this to break mix-blend-mode. Tested in Firefox 75 and Chrome 81. */
}

#wrapper .hoverlabel::before {
    position: absolute;
    content: "";
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    mix-blend-mode: multiply;
    z-index: 90;
    background-color: rgba(147, 213, 0, 0.95);
}   

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接