How can I set mix-blend-mode on an element, but not it's children? Setting the children to the default value of normal
does not seem to work:

- 2,236
- 3
- 24
- 34
-
It is the same issue as with opacity. It is not really that the property is inherited, it is that all the block is rendered with this effect – vals Jul 25 '15 at 20:36
5 Answers
The solution on how to avoid mix-blend-mode
affects children:
- Make child element position relative, give it a width and height;
- Create some real or pseudo element inside the child with absolute position, and apply
mix-blend-mode
to it; - Create
inner
element inside the child for your content. Make it's position absolute, and put it on top of other elements;
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;
}

- 308
- 6
- 15

- 3,279
- 2
- 18
- 39
I know this was asked over two years ago, but it could be useful in the future as it could be a better solution than creating pseudo-elements.
There is the CSS isolation
property that allows to choose wether the child element should be rendered in its parent's context (auto
) or as part of a new context, thus without any blend mode applied to it (isolate
).
Check out this page for examples

- 1,053
- 2
- 15
- 28
-
2If I'm right isolation only guards siblings of an element against mix-blend-mode. It does not work on children. – Driesketeer Mar 10 '20 at 12:54
someone commented that the the whole block is rendered with the effect and that is why you're having the issue. I am able to accomplish what you're are trying to do by removing the h1 from the block, position absolute, and a z-index of 1. here is a jsfiddle to show the effect.
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;
}

- 1,697
- 12
- 17
-
2Well that is a tough question. While it accomplishes what you want you may not consider this a solution and I can understand that. However in my experience I have found sometimes to accomplish the css styling you want sometimes you have to do things in a round about way. – Jpsh Jul 26 '15 at 16:25
It’s impossible to remove an element’s mix-blend-mode
from its children.
MDN says that mix-blend-mode
:
sets how an element's content should blend with the content of the element's parent and the element's background
To achieve the desired effect, place the child in a separate stacking context and make sure it renders on top of the element with mix-blend-mode
set.
You need two things to make this work:
- Make sure that your opaque content (your text) is not a child of the element that sets the background and the blend mode. For example, with CSS Grid Layout.
- Make sure the text is rendered over, and thus not affected by, the element that sets the background and the blend mode. Setting
mix-blend-mode
on your background will create a stacking context for it, and you may need to give your content its own stacking context to ensure it gets rendered above it.
Position your elements with CSS Grid:
- define a grid container with one auto-sized grid area
- place both the background element and the text element into that one grid area (so that they overlap)
- let the text element dictate the size of the grid area
- have the background element stretch to the size of the grid area, which is dictated by the size of the text element
Then, set isolation: isolate
on the text element to ensure it gets rendered above, and not under the background element.
A working example
.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>

- 474
- 2
- 4
An important note if you're using the excellent pseudoelement ::before/::after solution posted by Rashad Ibrahimov.
I found that I had to remove z-index from the parent element and apply it only to the pseudoelements and child elements before mix-blend-mode: multiply
would work.
For example
#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);
}

- 53
- 1
- 8