Why don't CSS blend modes work when applied against the document body?
Asked Answered
O

1

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?

Oleoresin answered 22/9, 2017 at 7:13 Comment(1)
Known issue with Chrome, it would seem. #40664900 #43504255 Looks fine for me in Firefox.Frosted
M
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>
Metallize answered 22/9, 2017 at 7:33 Comment(3)
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.Frosted
@Frosted - Really, I've no idea, but looking at the spec it does say that the backdrop is the result of compositing all previous elements.. Maybe the Chrome devs consider that the canvas does not constitute a previous element.Metallize
@Metallize 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 -__-Oleoresin

© 2022 - 2024 — McMap. All rights reserved.