5

Here's an example of CSS blend modes working against a specified "background" element:

body {
  position: relative;
}

.background {
  position: absolute;
  top: 0; left: 0;
  height: 100%;
  width: 100%;
  background: linear-gradient(red, blue);
}

.blend {
  background: green;
  mix-blend-mode: difference;
}
<body>
  <div class="background"></div>
  <div class="blend">BLEND ME</div>
</body>

And here's an example of the blend mode not applying over the body:

body {
  background-image: linear-gradient(red, blue);
  background-size: 100%;
  background-repeat: no-repeat;
}

.blend {
  background: green;
  mix-blend-mode: difference;
}
<body>
  <div class="blend">BLEND ME</div>
</body>

What gives? Is the body element not considered when calculating CSS blend modes? Does this apply in all browsers? Who am I and why am I here? This came up as an issue when attempting to implement dynamic (via scroll) blending over a body with background-attachment: fixed.

UPDATE: This appears to only apply in Chrome; Firefox/Safari behave expectedly - what's up with Chrome?

benjaminben
  • 113
  • 2
  • 7
  • 4
    Known issue with Chrome, it would seem. https://stackoverflow.com/questions/40664400/mix-blend-mode-issues-in-chrome https://stackoverflow.com/questions/43503755/did-chrome-safari-recently-change-the-way-mix-blend-mode-is-handled Looks fine for me in Firefox. – BoltClock Sep 22 '17 at 07:23

1 Answers1

6

The body element does blend in Chrome, but only if its background isn't propagated to the canvas.

To stop it doing that, add a background for the <html> element.

html {
  background-color: white;
}
body {
  background-image: linear-gradient(red, blue);
  background-size: 100%;
  background-repeat: no-repeat;
}
.blend {
  background: green;
  mix-blend-mode: difference;
}
<body>
  <div class="blend">BLEND ME</div>
</body>
Alohci
  • 78,296
  • 16
  • 112
  • 156
  • Why does Firefox have no trouble blending the background even when it's propagated to the viewport? Additionally, if the author does intend for the background to be propagated, Chrome does still fail to blend it when applying the gradient to the html element instead of the body element. This seems to be more of an issue with the canvas than the html or body elements. – BoltClock Sep 22 '17 at 07:39
  • @BoltClock - Really, I've no idea, but looking at the spec it does say that the backdrop is [the result of compositing all previous elements.](https://drafts.fxtf.org/compositing-1/#backdropCalc). Maybe the Chrome devs consider that the canvas does not constitute a previous *element*. – Alohci Sep 22 '17 at 07:43
  • @Alohci accepted because this is super helpful for my particular use case, though I'm still very curious as to _why_ this is going on in chrome... lazy me not even bothering to check more browsers before asking -__- – benjaminben Sep 22 '17 at 16:28