htmlcssmix-blend-modebackground-blend-mode

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


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?


Solution

  • 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>